Jackson: Custom JSON deserializer - java

I am using Jackson library's ObjectMapper for deserializing JSON into Java objects. I am using Spring 'wiring'. I have created custom deserializers to do the conversion from JSON string to POJO. However, when the input is bad (eg. a number is passed as "124A" - illegal character) a default deserialiser is invoked and bombs with the NumberFormatException. Is there a way to prevent default converters from being called?

Ok, given that input is not valid JSON (numbers can not start with or contain '$'), deserializer will not be called, and any change would have to apply to parser. There are no switches in Jackson to allow such content to be considered numbers.
If you can control input, just change value to a String (add double-quotes around value). Parser then passes it as JSON String, and data binding components get a chance to handle it (JsonDeserializer).

Related

Jackson ObjectMapper to process JSON and non-JSON inputs

TL;DR
How can Jackson's ObjectMapper be made to work for deserializing an object when sometimes the input is serialized JSON and sometimes it is a non-JSON string?
Details
I'm a Java/Jackson noob and have been banging my head against this all day.
I'm working in the context of a system that user ObjectMapper to deserialize inputs. I'm familiar with the Jackson annotations to make that work. And there's no problem when the input is serialized JSON.
The problem is I'm being provided a variety of inputs, some of which are not serialized JSON. I've seen answers related to polymorphic deserialization in which the serialized JSON may come in one of a variety of forms. That doesn't address the issue of how to handle input that is not serialized JSON at all.
I've tried using #JsonDeserialize to specify custom deserializers that extend StdDeserializer and JsonDeserializer. The problem in both cases is the JsonParser passed into the deserialize or deserializeWithType methods processes the input string before reaching my code, and so in the case of a non-JSON input the result is a JsonParseException.
So, is there a way to handle this? I'm working in the context of a larger system that expects ObjectMapper to do the work and, if possible, I'd like not to change that aspect of the system.

Extracting name/value pairs with variable end of name from JSON during deserialization

Is it possible to use Jackson's ObjectMapper to create Java objects from JSON which contains names haven a knwon beginning ("customfield") and a variable ending (which is the ID of a databse in fact).
So in a JSON you can find something like this:
"customfield_10000":null
or
"customfield_10002":"hello"
or
"customfield_10005":["com.atlassian.greenhopper.service.sprint.Sprint#1cc5ffd5[id=1,rapidViewId=1,state=ACTIVE,name=Sample Sprint 2,startDate=2017-11-30T02:29:06.805+01:00,endDate=2017-12-14T02:49:06.805+01:00,completeDate=<null>,sequence=1,goal=<null>]"]
These customfields are not part of any POJO, they just come with an event and I have to handle the incoming JSON.
I have to work with these fields so that I am not allowed to ignore them at all but it seems as if I have to handle them separately. ...I just don't know how.

Jackson: avoid deserialization of some fields but not ignoring them

i need to carry all the json data (to store them, log, return) but i will never access them from code. is there any way to avoid deserializing them but still use them during serialization?
class MyObject {
int importantField; // i want this field to be properly deserialized
String notImportantJsonGarbage; // i don't care what's here. it must be a valid json
}
So now i'd like to be able to deserialize it from
{"importantField":7, "notImportantJsonGarbage":{"key1":3, "key2":[1,2,3]}}
and later serialize it to the same string
UPDATE
i don't want to ignore this property. i need this data. but as a string, not fully deserialized object
i need to be able to do:
json1 -> object -> json2
json1 == json2
Take a look at: JsonProperty.Access
AUTO - Access setting which means that visibility rules are to be used to automatically determine read- and/or write-access of
this property.
READ_ONLY - Access setting that means that the property may only be read for serialization, but not written (set) during
deserialization.
READ_WRITE - Access setting that means that the property will be accessed for both serialization (writing out values as
external representation) and deserialization (reading values from
external representation), regardless of visibility rules.
WRITE_ONLY - Access setting that means that the property may only be written (set) for deserialization, but will not be read
(get) on serialization, that is, the value of the property is not
included in serialization.
So in your case you could use it like this:
#JsonProperty(access = Access.READ_ONLY)
private String notImportantJsonGarbage;
You can use annotation #JsonIgnoreover the property that you wish to ignore
You can use the type JSONObject for the Json field.
private JSONObject notImportantJsonGarbage;
And when you need to read that, you can convert it to a String (or other type). You can use jackson or gson libraries to achieve that.
Note that when you convert the JsonObject back to String, the resulting string might have the quotes escaped.
Using JSONObject also solves your requirement of 'must be a valid json object'.

java/jersey/jackson - validate input JSON

I am writing a REST API with a Java/Jersey/Jackson stack. All JSON parsing and generating is done with Jackson. The REST layer is handled by Jersey. It will be embedded in a Grizzly container.
In my API, I accept JSON in my endpoints. For example:
#POST
public Response post(final SomeObject input) {
return ...;
}
What is the best way to validate the input? There are certain things I would like to validate:
input must be not null
certain fields of input must be not null
certain fields of input must follow a regular expression (text fields)
certain fields of input must be in a range (numeric fields)
...
If possible, I would like to change my code as less as possible. That is, I prefer to annotate my classes, methods and parameters to integrate the validation.
You can use a JSON Schema.
And since you use Jackson, you can use my library which does exactly that.
However this means you'd need to change your logic so that you receive the JSON (as a JsonNode) instead of the serialized POJO, and only then serialize to your POJO.
You can also BeanValidationApi (javax.validation.constraints) and then annotate your fields with #NotNull,#Pattern, etc. Jersey also provides Bean Validation Support

Jackson JSON converts integers into strings

I am using the object mapper to map into an object that has String variables. This works a little too well, because even integers and booleans from the JSON are converted into Strings.
Example:
{"my_variable":123}
class MyClass{
String my_variable;
}
I would like the object mapper to report an error in this kind of situation instead of converting 123 into a string for my_variable. Is this possible?
There is currently no such configuration, but you can override default deserializer with a custom one (see fasterxml wiki) and make that throw an exception?
If you would like a more convenient way you can file a Jira enhancement request; for example, new DeserializationConfig.Feature.COERCE_STRINGS_AS_NUMBERS (default to true) that one could disable to prevent such coercion.

Categories