JsonIgnore annotation doesn't seem to work for me. Any ideas why?
public class JsonTest implements Serializable {
#JsonIgnore
private static JsonTest instance = null;
#JsonIgnore
private transient Set<String> set = new CopyOnWriteArraySet<String>();
private JsonTest() {}
#JsonIgnore
public static JsonTest getInstance() {
if (instance == null)
instance = new JsonTest();
return instance;
}
public void setSet(Set<String> set) {
this.set = set;
}
#JsonIgnore
public Set<String> getSet() {
return set;
}
public String toString() {
ObjectMapper mapper = new ObjectMapper();
mapper.configure(SerializationConfig.Feature.FAIL_ON_EMPTY_BEANS, false);
try {
return mapper.writeValueAsString(this);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
public static void main(String[] args) {
HashSet<String> set = new HashSet<String>();
set.add("test");
JsonTest.getInstance().setSet(set);
System.out.println(JsonTest.getInstance().toString());
}
}
Output: {"set":["test"]}
Transient means that that field will not be serialized. You do not need to add #JsonIgnore annotation there because of that field will be excluded anyway.
You can locate #JsonIgnore annotation at least in org.codehaus.jackson:jackson-mapper-asl:1.9.13 and com.fasterxml.jackson.core:jackson-annotations:2.4.3 (this is what I used). Where ObjectMapper is in jackson-mapper-asl artifact. The interesting part here is that if I use #JsonIgnore from jackson-annotations (com.fasterxml.jackson.annotation.JsonIgnore) -- it doesn't work ('set' is in response) even if I configure ObjectMapper to use only properties. Probably it is a bug in fasterxml implementation but I didn't find it.
So, it is working fine if you will use codehaus rather then fasterxml (I added configuration to use only fields):
import org.codehaus.jackson.annotate.JsonAutoDetect;
import org.codehaus.jackson.annotate.JsonIgnore;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.map.SerializationConfig;
import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;
public class JsonTest implements Serializable {
#JsonIgnore
private static JsonTest instance = null;
private transient Set<String> set = new CopyOnWriteArraySet<String>();
private JsonTest() {}
#JsonIgnore
public static JsonTest getInstance() {
if (instance == null)
instance = new JsonTest();
return instance;
}
public void setSet(Set<String> set) {
this.set = set;
}
#JsonIgnore
public Set<String> getSet() {
return set;
}
public String toString() {
ObjectMapper mapper = new ObjectMapper();
mapper.configure(SerializationConfig.Feature.FAIL_ON_EMPTY_BEANS, false);
mapper.setVisibilityChecker(mapper.getSerializationConfig().getDefaultVisibilityChecker()
.withFieldVisibility(JsonAutoDetect.Visibility.ANY)
.withGetterVisibility(JsonAutoDetect.Visibility.NONE)
.withSetterVisibility(JsonAutoDetect.Visibility.NONE)
.withCreatorVisibility(JsonAutoDetect.Visibility.NONE));
try {
return mapper.writeValueAsString(this);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
public static void main(String[] args) {
HashSet<String> set = new HashSet<String>();
set.add("test");
JsonTest.getInstance().setSet(set);
System.out.println(JsonTest.getInstance().toString());
}
}
Related
I have a JSON file
{
"readServiceAuthorizationResponse": {
"serviceAuthorization": {
"serviceAuthorizationId": "50043~220106065198",
"status": "Approved",
"receivedDate": "2022-1-6 1:21:12 PM",
"providerFirstName": "Ranga",
"providerLastName": "Thalluri",
"organizationName": "General Hospital",
"serviceLines": [{
"statusReason": "Approved",
"procedureDescription": "Room & board ward general classification",
"requestedQuantity": "1.00",
"approvedQuantity": "1.00",
"deniedQuantity": "",
"quantityUnitOfMeasure": "Day(s)",
"providers": [{
"providerFirstName": "Ranga",
"providerLastName": "Thalluri",
"organizationName": ""
}]
}]
}
}
}
My Java to read this into an object is this:
package com.shawn.dto;
import java.nio.file.Files;
import java.nio.file.Paths;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.databind.ObjectMapper;
#JsonIgnoreProperties(ignoreUnknown = true)
public class ServiceAuthorizationDTO {
public String serviceAuthorizationId;
public String status;
public String receivedDate;
public String providerFirstName;
public String providerLastName;
public String organizationName;
public ServiceLine[] serviceLines;
public static ServiceAuthorizationDTO create(String json) {
ObjectMapper m = new ObjectMapper();
try {
Outer outer = m.readValue(json, Outer.class);
return outer.readServiceAuthorizationResponse.serviceAuthorization;
} catch (Exception e) {
return null;
}
}
#JsonIgnoreProperties(ignoreUnknown = true)
static class ReadServiceAuthorizationResponse {
public ServiceAuthorizationDTO serviceAuthorization;
}
#JsonIgnoreProperties(ignoreUnknown = true)
static class Outer {
public ReadServiceAuthorizationResponse readServiceAuthorizationResponse;
}
#JsonIgnoreProperties(ignoreUnknown = true)
public static class ServiceLine {
String statusReason;
String procedureDescription;
String requestedQuantity;
String approvedQuantity;
String deniedQuantity;
String quantityUnitOfMeasure;
Provider[] providers;
}
#JsonIgnoreProperties(ignoreUnknown = true)
public static class Provider {
String providerFirstName;
String providerLastName;
String organizationName;
}
public static void main(String[] args) {
try {
String json = new String(Files.readAllBytes(Paths.get("c:/temp/test.json")));
ServiceAuthorizationDTO dao = ServiceAuthorizationDTO.create(json);
System.out.println("serviceAuthorizationId: " + dao.serviceAuthorizationId);
System.out.println("serviceLines[0].procedureDescription: " + dao.serviceLines[0].procedureDescription);
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
}
When I run it I get this:
serviceAuthorizationId: 50043~220106065198
serviceLines[0].procedureDescription: null
The outer fields in the object like providerId are read from the JSON. But the serviceLines array shows 1 element, and all fields in that class are empty.
Any ideas? This is the first time I've used real objects with JSON. I've always mapped it into Map objects and pulled the fields out manually. Thanks.
Fields in classes ServiceLine and Provider have package-private access modifiers. Jackson can't deserialize into private fields with its default settings. Because it needs getter or setter methods.
Solution 1: Make fields public
public static class ServiceLine {
public String statusReason;
public String procedureDescription;
public String requestedQuantity;
public String approvedQuantity;
public String deniedQuantity;
public String quantityUnitOfMeasure;
public Provider[] providers;
}
Solution 2: Use #JsonAutoDetect annotation
#JsonIgnoreProperties(ignoreUnknown = true)
#JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY)
public class ServiceLine {
String statusReason;
String procedureDescription;
String requestedQuantity;
String approvedQuantity;
String deniedQuantity;
String quantityUnitOfMeasure;
Provider[] providers;
}
Solution 3: Change visibility on the ObjectMapper (doc)
public static ServiceAuthorizationDTO create(String json) {
ObjectMapper objectMapper = new ObjectMapper();
try {
objectMapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY);
Outer outer = objectMapper.readValue(json, Outer.class);
return outer.readServiceAuthorizationResponse.serviceAuthorization;
} catch (Exception e) {
return null;
}
}
I am trying to convert xml to json. First I created java class using the following xml
<CompositeResponse>
<CompositeIndividualResponse>
<PersonIdentification>2222</PersonIdentification>
</CompositeIndividualResponse>
</CompositeResponse>
The following java classes are following:
public class Main {
public CompositeResponse CompositeResponse;
public CompositeResponse getCompositeResponse() {
return CompositeResponse;
}
public void setCompositeResponse(CompositeResponse CompositeResponse) {
this.CompositeResponse = CompositeResponse;
}
}
public class CompositeResponse {
private List<CompositeIndividualResponse> CompositeIndividualResponse;
public List<CompositeIndividualResponse> getCompositeIndividualResponse() {
return CompositeIndividualResponse;
}
public void setCompositeIndividualResponse(List<CompositeIndividualResponse> CompositeIndividualResponse) {
CompositeIndividualResponse = CompositeIndividualResponse;
}
}
public class CompositeIndividualResponse {
private String Persondentification;
public String getPersondentification() {
return Persondentification;
}
public void setPersonIdentification (String PersonIdentification) {
this.PersonIdentification = PersonIdentification;
}
}
I am using the following code for conversion:
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
public class XMLToJson {
public static void main(String[] args) throws IOException {
String content = new String(Files.readAllBytes(Paths.get("test.xml")));
XmlMapper xmlMapper = new XmlMapper();
Main poppy = xmlMapper.readValue(content, Main.class);
ObjectMapper mapper = new ObjectMapper();
String json = mapper.writeValueAsString(poppy);
System.out.println(json);
}
}
But i am getting the following exception that CompositeIndividualResponse is not recognized.
Exception in thread "main" com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "CompositeIndividualResponse" (class com.test.custom.copy.Main), not marked as ignorable (2 known properties: "CompositeResponse", "compositeResponse"])
at [Source: (StringReader); line: 3, column: 32] (through reference chain: com.test.custom.copy.Main["CompositeIndividualResponse"])
I believe my java pojo is not fit with xml data. So how to define collection of pojo to solve this problem so I can get the following json:
{
"CompositeResponse":{
"CompositeIndividualResponse":
[
{
"PersonSSNIdentification":"221212501"
}
]
}
}
Define you POJO like this,
public class CompositeResponse {
private List<CompositeIndividualResponse> compositeIndividualResponse;
public List<CompositeIndividualResponse> getCompositeIndividualResponse() {
return compositeIndividualResponse;
}
public void setCompositeIndividualResponse(List<CompositeIndividualResponse> compositeIndividualResponse) {
CompositeIndividualResponse = compositeIndividualResponse;
}
}
public class CompositeIndividualResponse {
private String personIdentification;
public String getPersonIdentification() {
return personIdentification;
}
public void setPersonIdentification (String personIdentification) {
this.personIdentification= personIdentification;
}
}
Then update your main program as below,
public class XMLToJson {
public static void main(String[] args) throws IOException {
String content = new String(Files.readAllBytes(Paths.get("test.xml")));
XmlMapper xmlMapper = new XmlMapper();
CompositeResponse poppy = xmlMapper.readValue(content, CompositeResponse.class);
ObjectMapper mapper = new ObjectMapper();
String json = mapper.writeValueAsString(poppy);
System.out.println(json);
}
}
Problem in field naming, all fields by default starts with small letter.
for example: compositeResponse
To avoid this problem add annotation #JsonProperty for each field, like this:
#JsonProperty("persondentification")
private String Persondentification;
The solution is I do not need the Main.java class. Also I need to add jackson annotation to define xml element. The working code is following.
CompositeResponse.java
public class CompositeResponse {
#JacksonXmlProperty(localName = "CompositeIndividualResponse")
#JacksonXmlElementWrapper(localName = "CompositeIndividualResponse",useWrapping = false)
private List<CompositeIndividualResponse> compositeIndividualResponse;
public List<CompositeIndividualResponse> getCompositeIndividualResponse() {
return compositeIndividualResponse;
}
public void setCompositeIndividualResponse(List<CompositeIndividualResponse> compositeIndividualResponse) {
this.compositeIndividualResponse = compositeIndividualResponse;
}
}
CompositeIndividualResponse.java:
public class CompositeIndividualResponse {
#JacksonXmlProperty(localName = "PersonIdentification")
private String personIdentification;
public String getPersonIdentification() {
return personIdentification;
}
public void setPersonIdentification (String personIdentification) {
this.personIdentification= personIdentification;
}
}
XMLToJson.java
public class XMLToJson {
public static void main(String[] args) throws IOException {
String content = new String(Files.readAllBytes(Paths.get("test.xml")));
XmlMapper xmlMapper = new XmlMapper();
CompositeResponse poppy = xmlMapper.readValue(content, CompositeResponse.class);
ObjectMapper mapper = new ObjectMapper();
String json = mapper.writeValueAsString(poppy);
System.out.println(json);
}
}
While assigning values from DTO to different entity names, I assigned correctly with the help of JsonProperty. FrontEnd expecting in a different name. Values for DTO object will get from different object. That I have to assign to entity. Instead of using plain java and copying, am using objectmapper. Here then entity values will be used by frontend. How to print the entity values in different name? Please check below code.
//DTO Class
import java.util.List;
public class StaffDTO {
private String nameDT;
private List<String> skillDT;
//Getter and Setters
}
//Entity Class
import java.util.List;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
#JsonInclude(JsonInclude.Include.NON_NULL)
#JsonPropertyOrder({
"nameDT",
"skillDT"
})
public class Staff {
#JsonProperty("nameDT")
private String name;
#JsonProperty("skillDT")
private List<String> skills;
//Getter and Setters
}
//Call Method
import java.util.ArrayList;
import java.util.List;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
public class SeatMapCall1 {
public static void main(String[] args) {
try {
StaffDTO staffDTO = createDummyObject();
System.out.println(convertObjectToJson(staffDTO));
Staff staff= convertJsonToObject(convertObjectToJson(staffDTO),Staff.class);
System.out.println(convertObjectToJson(staff));
} catch (Throwable e) {
e.printStackTrace();
}
}
private static <T> T convertJsonToObject(String jsonStrRes,
Class<T> classArg) {
T resObj = null;
try {
ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
resObj = mapper.readValue(jsonStrRes, classArg);
} catch (Throwable e) {
e.printStackTrace();
}
return resObj;
}
public static <T> String convertObjectToJson(T obj) {
String jsonStringReq = null;
ObjectMapper objMapper = new ObjectMapper();
try {
jsonStringReq = objMapper.writeValueAsString(obj);
} catch (Exception e) {
}
return jsonStringReq;
}
private static StaffDTO createDummyObject() {
StaffDTO staffDTO = new StaffDTO();
staffDTO.setNameDT("mkyong");
List<String> skills = new ArrayList<>();
skills.add("java");
skills.add("python");
staffDTO.setSkillDT(skills);
return staffDTO;
}
}
//Displays output as
{"nameDT":"mkyong","skillDT":["java","python"]}
{"nameDT":"mkyong","skillDT":["java","python"]}
But I want
{"nameDT":"mkyong","skillDT":["java","python"]}
{"name":"mkyong","skills":["java","python"]}
If I use the below getter and setters in Staff class, I am getting expected as below
{"nameDT":"mkyong","skillDT":["java","python"]}
{"nameDT":"mkyong","skillDT":["java","python"],"name":"mkyong","skills":["java","python"]}
Here it includes both nameDT, skillDT and name, skills. I don't need nameDT, skillDT.
#JsonProperty("nameDT")
private String nameDT;
#JsonProperty("skillDT")
private List<String> skillDT;
public String getName()
{ return nameDT; }
public void setName(String nameDT)
{ this.nameDT = nameDT; }
public List<String> getSkill()
{ return skillDT; }
public void setSkill(List<String> skillDT)
{ this.skillDT = skillDT; }
I want to include only fields in my classes that have my custom annotation #MyInclude but Jackson ends up ignoring everything. What am I doing wrong?
public static void main(String[] args) throws Exception {
ObjectMapper mapper = new ObjectMapper();
mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
mapper.setAnnotationIntrospector(new IgnoreIntrospector());
MyNestedObject nestedObject = new MyNestedObject("value1", "value2");
MyObject object = new MyObject();
object.setNestedObject(nestedObject);
String json = mapper.writeValueAsString(object); //This returns {}
}
public static class IgnoreIntrospector extends JacksonAnnotationIntrospector {
private static final long serialVersionUID = -3951086067314107368L;
#Override
public boolean hasIgnoreMarker(AnnotatedMember m) {
return !m.hasAnnotation(MyInclude.class) || super.hasIgnoreMarker(m);
}
}
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
#Data
#NoArgsConstructor
#AllArgsConstructor
public class MyObject {
#MyInclude
private MyNestedObject nestedObject;
}
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
#Data
#NoArgsConstructor
#AllArgsConstructor
public class MyNestedObject {
#MyInclude
private String value1;
private String value2;
}
mapper.writeValueAsString(object) is returning {} but it should return NestedObject with value1 populated instead (ignoring value2).
If I update my IgnoreIntrospector.hasIgnoreMarker () to just super.hasIgnoreMarker(m) then everything would be included in the json string.
The IgnoreIntrospector alone wasn't enough. Since my custom annotations were only on fields, I needed to disable all visibility:
mapper.setAnnotationIntrospector(new IgnoreIntrospector());
mapper.setVisibility(mapper.getSerializationConfig().getDefaultVisibilityChecker()
.withFieldVisibility(JsonAutoDetect.Visibility.ANY)
.withGetterVisibility(JsonAutoDetect.Visibility.NONE)
.withSetterVisibility(JsonAutoDetect.Visibility.NONE)
.withCreatorVisibility(JsonAutoDetect.Visibility.NONE));
mapper.setVisibility(mapper.getDeserializationConfig().getDefaultVisibilityChecker()
.withFieldVisibility(JsonAutoDetect.Visibility.ANY)
.withGetterVisibility(JsonAutoDetect.Visibility.NONE)
.withSetterVisibility(JsonAutoDetect.Visibility.NONE)
.withCreatorVisibility(JsonAutoDetect.Visibility.NONE));
And updated my IgnoreIntrospector:
public static class IgnoreIntrospector extends JacksonAnnotationIntrospector {
#Override
public boolean hasIgnoreMarker(AnnotatedMember m) {
return m instanceof AnnotatedField && _findAnnotation(m, MyInclude.class) == null;
}
}
Alternatively, override both hasIgnoreMarker() and findNameForSerialization():
JsonMapper jsonMapper = JsonMapper.builder()
.annotationIntrospector(new JacksonAnnotationIntrospector()
{
#Override
public boolean hasIgnoreMarker(AnnotatedMember m)
{
return m.hasAnnotation(CustomIgnore.class) || super.hasIgnoreMarker(m);
}
#Override
public PropertyName findNameForSerialization(Annotated a)
{
if(a.hasAnnotation(CustomIgnore.class)) return null;
return super.findNameForSerialization(a);
}
})
.build();
I am consuming a "RESTful" service (via RestTemplate) that produces JSON as follows:
{
"id": "abcd1234",
"name": "test",
"connections": {
"default": "http://foo.com/api/",
"dev": "http://dev.foo.com/api/v2"
},
"settings": {
"foo": "{\n \"fooId\": 1, \"token\": \"abc\"}",
"bar": "{\"barId\": 2, \"accountId\": \"d7cj3\"}"
}
}
Note the settings.foo and settings.bar values, which cause issues on deserialization. I would like to be able to deserialize into objects (e.g., settings.getFoo().getFooId(), settings.getFoo().getToken()).
I was able to solve this specifically for an instance of Foo with a custom deserializer:
public class FooDeserializer extends JsonDeserializer<Foo> {
#Override
public Foo deserialize(JsonParser jp, DeserializationContext ctx) throws IOException {
JsonNode node = jp.getCodec().readTree(jp);
String text = node.toString();
String trimmed = text.substring(1, text.length() - 1);
trimmed = trimmed.replace("\\", "");
trimmed = trimmed.replace("\n", "");
ObjectMapper mapper = new ObjectMapper();
JsonNode obj = mapper.readTree(trimmed);
Foo result = mapper.convertValue(obj, Foo.class);
return result;
}
}
#Data
#JsonIgnoreProperties(ignoreUnknown = true)
public class Settings {
#JsonDeserialize(using = FooDeserializer.class)
private Foo foo;
private Bar bar;
}
However, now if I want to deserialize settings.bar, I need to implement another custom deserializer. So I implemented a generic deserializer as follows:
public class QuotedObjectDeserializer<T> extends JsonDeserializer<T> implements ContextualDeserializer {
private Class<?> targetType;
private ObjectMapper mapper;
public QuotedObjectDeserializer(Class<?> targetType, ObjectMapper mapper) {
this.targetType = targetType;
this.mapper = mapper;
}
#Override
public JsonDeserializer<T> createContextual(DeserializationContext context, BeanProperty property) {
this.targetType = property.getType().containedType(1).getRawClass();
return new QuotedObjectDeserializer<T>(this.targetType, this.mapper);
}
#Override
public T deserialize(JsonParser jp, DeserializationContext context) throws IOException {
JsonNode node = jp.getCodec().readTree(jp);
String text = node.toString();
String trimmed = text.substring(1, text.length() - 1);
trimmed = trimmed.replace("\\", "");
trimmed = trimmed.replace("\n", "");
JsonNode obj = this.mapper.readTree(trimmed);
return this.mapper.convertValue(obj, this.mapper.getTypeFactory().constructType(this.targetType));
}
}
Now I'm not sure how to actually use the deserializer, as annotating Settings.Foo with #JsonDeserialize(using = QuotedObjectDeserializer.class) obviously does not work.
Is there a way to annotate properties to use a generic custom deserializer? Or, perhaps more likely, is there a way to configure the default deserializers to handle the stringy objects returned in my example JSON?
Edit: The problem here is specifically deserializing settings.foo and settings.bar as objects. The JSON representation has these objects wrapped in quotes (and polluted with escape sequences), so they are deserialized as Strings.
Sorry about the length of the code here. There are plenty of shortcuts here (no encapsulation; added e to defaulte to avoid keyword etc.) but the intent is there
Model class:
package com.odwyer.rian.test;
import java.io.IOException;
import org.apache.commons.lang3.builder.ReflectionToStringBuilder;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
public class Model {
public String id;
public String name;
public Connections connections;
public Settings settings;
public static class Connections {
public String defaulte;
public String dev;
#Override
public String toString() {
return ReflectionToStringBuilder.toString(this);
}
}
public static class Foo {
public Foo () {}
#JsonCreator
public static Foo create(String str) throws JsonParseException, JsonMappingException, IOException {
return (new ObjectMapper()).readValue(str, Foo.class);
}
public Integer fooId;
public String token;
#Override
public String toString() {
return ReflectionToStringBuilder.toString(this);
}
}
public static class Bar {
public Bar() {}
#JsonCreator
public static Bar create(String str) throws JsonParseException, JsonMappingException, IOException {
return (new ObjectMapper()).readValue(str, Bar.class);
}
public Integer barId;
public String accountId;
#Override
public String toString() {
return ReflectionToStringBuilder.toString(this);
}
}
public static class Settings {
public Foo foo;
public Bar bar;
#Override
public String toString() {
return ReflectionToStringBuilder.toString(this);
}
}
#Override
public String toString() {
return ReflectionToStringBuilder.toString(this);
}
}
The caller:
package com.odwyer.rian.test;
import java.io.File;
import java.io.IOException;
import java.util.Scanner;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
public class TestClass {
private static ObjectMapper objectMapper = new ObjectMapper();
public static void main(String[] args) throws JsonParseException, JsonMappingException, IOException {
Scanner file = new Scanner(new File("test.json"));
String jsonStr = file.useDelimiter("\\Z").next();
Model model = objectMapper.readValue(jsonStr, Model.class);
System.out.println(model.toString());
}
}
The result (too much hassle to format out but it is all there!):
com.odwyer.rian.test.Model#190083e[id=abcd1234,name=test,connections=com.odwyer.rian.test.Model$Connections#170d1f3f[defaulte=http://foo.com/api/,dev=http://dev.foo.com/api/v2],settings=com.odwyer.rian.test.Model$Settings#5e7e6ceb[foo=com.odwyer.rian.test.Model$Foo#3e20e8c4[fooId=1,token=abc],bar=com.odwyer.rian.test.Model$Bar#6291bbb9[barId=2,accountId=d7cj3]]]
The key, courtesy of Ted and his post (https://stackoverflow.com/a/8369322/2960707) is the #JsonCreator annotation