JacksonProviderProxy writing out null values in json output - json

I have a simple POJO class that extends another simple POJO class. I am using the com.sun.jersey.json.impl.provider.entity.JacksonProviderProxy to marshall the properties in these POJO classes to JSON. However, when I set some of the properties to the POJO as null, then it outputs those properties as the string null instead of not outputting it at all.
for eg.
{
Person:
[{
"firstName":"John"
"lastName":"null"
}]
}
instead of:
for eg.
{
Person:
[{
"firstName":"John"
}]
}

Different options are available for suppressing serialization of properties with null values, depending on the version of Jackson in use, and whether the ObjectMapper can be directly configured.
With Jackson 1.1+, with direct access to configure the ObjectMapper, you could just call setSerializationInclusion(Include.NON_NULL).
Alternatively, you could annotate the (class) type that has the properties, for which null properties serialization is to be suppressed, with #JsonSerialize(include=Inclusion.NON_NULL).
With Jackson 2+, instead of the #JsonSerialize annotation, use #JsonInclude(Include.NON_NULL).

Related

Jackson Map Null Json to List

I've searched and found Jackson ObjectMapper throwing NullPointerException even with NON_NULL, but I don't have control of the class to change my setter.
I have am being given
{... "fieldNames": null,...}
and am supposed to deserialize it to
Collection<String> fieldNames
I don't have control of the class or the json I'm getting.
Is there some setting I can use to handle for this? I've looked at DeserializationFeature, but could not find it
You can use mix-ins when you don't control the class you are deserializing. You don't mention the name of the class containing Collection<String> fieldNames so lets assume it's called Fields. Then create a new class:
class FieldsMixin {
#JsonSetter(nulls = Nulls.SKIP)
Collection<String> fieldNames;
}
and add the mixin class to your ObjectMapper associating it with the original unmodified class:
mapper.addMixIn(Fields.class, FieldsMixin.class);
This is a new feature in Jackson 2.9 and as you guess it will skip calling a setter method or otherwise set a field if the value in JSON is null. Documentation

Why I parse json into a Java List, but not a Scala List?

I am attempting to parse a json object that contains a list. I am able to parse the list if the field is backed by a Java List, but it fails if the field is backed by a Scala list. What is the difference between parsing into a Scala List vs a Java List, and what do I have to change to be able to parse this into a Scala List?
object JsonParsingExample extends App {
val objectMapper = new ObjectMapper()
// This line succeeds.
objectMapper.readValue("""{"list": ["a","b"]}""", classOf[JavaList])
// This line fails.
objectMapper.readValue("""{"list": ["a","b"]}""", classOf[ScalaList])
}
case class JavaList() {
#JsonProperty(value = "list")
var myList: java.util.ArrayList[String] = null
}
case class ScalaList() {
#JsonProperty(value = "list")
var myList: List[String] = null
}
The error message I receive is:
com.fasterxml.jackson.databind.JsonMappingException: Can not construct instance of scala.collection.immutable.List, problem: abstract types either need to be mapped to concrete types, have custom deserializer, or be instantiated with additional type information
Jackson doesn't know anything about Scala types by default (otherwise it would have to depend on scala-library). To teach it, use jackson-module-scala.
Because the scala.collection.immutable.List is actually an abstract class. Generally when you use List("a", "b", "c") is the object List.apply() which is coming from this line: https://github.com/scala/scala/blob/2.12.x/src/library/scala/collection/immutable/List.scala#L452 and that's actually an inner class (something called scala.collection.immutable.$colon$colon).

How to parse json arrary?

I have come across a problem of parsing json data . I am building project using spring boot based on REST api . When i have to parse data corresponding to domain then it is very easy , i use RequestBody in controller method with domain name but in current scenerio i have a list of domain in json form :
{
"data":[
{
"type":"abc",
"subtypes":[
{
"leftValue":"BEACH",
"rightValue":"MOUNTAIN",
"preferencePoint":60
},
{
"leftValue":"ADVENTURE",
"rightValue":"LEISURE",
"preferencePoint":60
}
]
},
{
"type":"mno",
"subtypes":[
{
"leftValue":"LUXURY",
"rightValue":"FUNCTIONAL",
"preferencePoint":60
},
{
"leftValue":"SENSIBLE",
"rightValue":"AGGRESIVE",
"preferencePoint":0
}
]
}
]
}
I am sending data in list where type is the property of class Type
and class Type has list of Subtypes class and subtype class contains leftValue and rightValue as enums
I am using spring boot which uses jackson liberary by default and i want to parse this data into corresponding Type class using Jackson. Can any one provide me solution.
It wasn't clear to me if you have static or dynamic payload.
Static payload
For static one, I would personally try to simplify your payload structure. But your structure would look like this. (I skipped getters and setters. You can generate them via Lombok library).
public class Subtype{
private String leftValue;
private String rightValue;
private int preferencePoint;
}
public class Type{
private String type;
private List<Subtype> subtypes;
}
public class Data{
private List<Type> data;
}
Then in your controller you inject Data type as #RequestBody.
Dynamic payload
For dynamic payload, there is option to inject LinkedHashMap<String, Object> as #RequestBody. Where value in that map is of type Object, which can be casted into another LinkedHashMap<String, Object> and therefore this approach support also nested objects. This can support infinite nesting this way. The only downside is that you need to cast Objects into correct types based on key from the map.
BTW, with pure Spring or Spring Boot I was always able to avoid explicit call against Jackson API, therefore I don't recommend to go down that path.

deserialize lazylist using jackson

I have a object which uses a org.apache.commons.collections.list.LazyList for one of its fields, which is serialized ti JSON. The JSON looks like this:
"myObject": ["org.apache.commons.collections.list.LazyList", [
{
"attr1": "asdasd",
"attr2": 1234
}
]],
The object field looks like this:
List<MyObject> myObject = ListUtils.lazyList(new ArrayList(), {new MyObject()} as Factory)
However trying to deserialize the above JSON using a Jackson ObjectMapper fails, since it can't find a default constructor for a LazyList - which makes sense. But how can I specify how this field can be deserialized?
Error message:
No default constructor for [collection type; class org.apache.commons.collections.list.LazyList, contains [simple type, class foo.bar.MyObject]]
Bounty-constraints:
To collect the bounty, this question needs to be answered using a custom jackson deserializer - the custom deserializer must not be field specific! Hence no solution using custom implementations of a LazyList for a specific type will answer this question adequately.
The solution below worked on both List and Map collection objects, it might also work on yours.
#JsonDeserialize(contentAs=MyObject.class)
private List<MyObject> myObject = ListUtils.lazyList(new ArrayList(), {new MyObject()} as Factory);

Jackson: how to treat {type:xx}?

I have the following json:
{"resourceWithType":
{"parentId":0,
"pluginId":0,
"pluginName":"Platforms",
"resourceId":10001,
"resourceName":"snert",
"typeId":10057,
"typeName":"Mac OS X"
}
}
And a class
public class ResourceWithType {
String resourceName;
int resourceId;
String typeName;
with all the getters and setters and so on.
The above JSON was actually created via RESTeasy and the Jettison provider where the class was marked with #XmlRootElement.
When I try to deserialize the above JSON via
ObjectMapper mapper=new ObjectMapper();
ResourceWithType rwt = mapper.readValue(json,ResourceWithType.class);
It fails with
06-13 11:07:55.360: WARN/System.err(26040):
org.codehaus.jackson.map.exc.UnrecognizedPropertyException:
Unrecognized field "resourceWithType"
(Class org.rhq.core.domain.rest.ResourceWithType),
not marked as ignorable
Which is sort of understandable.
How can I tell Jackson, that the embedded 'resourceWithType' is actually the class to deserialize into?
Other option would be to tell jettison not to include that type - how?
Tree model is a possibility; or just a simple wrapper like:
class {
public ResourceWithType resourceWithType;
}
to let you unwrap it. But often framework itself should handle unwrapping, since they are ones adding extra wrapping (Jackson does not add 'resourceWithType' in there by default).
Perhaps use the TreeModel API to unwrap the first (tag name) level, then deserialize the inner contents as usual (using the binding API)?