Open cowtowncoder opened 3 years ago
Example usage suggestion, made it verbose(not lambda) to express that we would need interface ValuePreprocessor
also.
class Bean {
public int hello;
}
// NEW FEATURE
ValuePreprocessor processor = new ValuePreprocessor() {
@Override
public String preprocess(String name, String expected) {
// do something... like trimming
return
}
}
// USAGE
@Test
public test() {
// polluted input
String input = a2q(" {`hello`:123} #_F#EFJ)#")
// configure it
ObjectMapper mapper = JsonMapper.builder()
.registerValuePreprocessor(processor)
.build();
// use it, successfully
assertNotNull(mapper.readValue(input, Bean.class));
assertThrows(SomeDeserException.class,
() -> mapper.reader()
.withoutValuePreprocessor() // <---- sometimes we may not want it?
.readValue(input, Bean.class));
}
I'd prefer if the new class was called ValuePreprocessor and it was aimed at allowing values to be modified. So in "name": "value"
, it would only be allowed to change the value
. I think the API in ValuePreprocessor should be public String preprocess(String name, String value)
. It may also be useful to have a 3rd input parameter, a type descriptor - it would be certainly be useful to know if the value is a number.
I don't know what to do about arrays like "name": [ "value1", "value2" ]
. The type descriptor could be an enum of string
, number
, string-array
, number-array
. With this example we could have 2 calls to the ValuePreprocessor with the inputs:
name
, value1
, string-array
name
, value2
, string-array
If we want to make the names preprocessable, we could add a separate feature to support a NamePreprocessor.
I'd prefer if the new class was called ValuePreprocessor
Sure, I don't have preference for name yet.
preprocess(String name, String value)
Seems like name
would be the JSON key to look for, but how will the parameter value
be used?
Seems like name would be the JSON key to look for, but how will the parameter value be used?
If you have JSON with this:
"name1": "value1"
You get a call to the ValuePreprocessor with this:
String preprocess(name1, value1)
The ValuePreprocessor is user provided and the user may have code in their ValuePreprocessor where they want to uppercase values but only when the name value is equal to name1
.
The ValuePreprocessor is user provided and the....
Thank you for the explanation 🙏🏼 I first thought the preprocessor would take in the whole input (like JSON String, .csv
or .json
file, etc...) and clean up input. But your usage makes sense also. I will go check again the intended usage.
P.S. Modified example usage accordingly.
The ValuePreprocessor is user provided and the....
Thank you for the explanation 🙏🏼 I first thought the preprocessor would take in the whole input (like JSON String,
.csv
or.json
file, etc...) and clean up input. But your usage makes sense also. I will go check again the intended usage.P.S. Modified example usage accordingly.
I could be wrong but I really don't see the point in jackson pre-processing the entire input as one string. A user can trivially do that already in their own code before asking Jackson to parse the modified input. But the ValuePreprocessor as I describe it is useful because the JSON parser has added some value by working out the structure of the input.
I could be wrong but I really don't see the point in jackson pre-processing the entire input as one string. A user can trivially do that already in their own code before asking Jackson to parse the modified input.
I concur 👍🏼
Correct: this would apply to String
valued (Object) properties, not to whole input document.
But I suspect that
https://github.com/FasterXML/jackson-core/issues/355
is more generally usable approach.
(note: counterpart to https://github.com/FasterXML/jackson-core/issues/355 -- see more discussion there)
For some use cases -- for example, variable substitution -- it would be beneficial to be able to register a handler that can replace parts of incoming String values before other databinding functionality handles it. Since there are various ways this could occur, I'll add a databinding issue here; the original
jackson-core
one (see above) may be most likely way to get there, but even if so there probably needs to be a way to register such handler on per-call basis forObjectReader
s (and/or maybeObjectMapper
).