I am using Spring MVC and spring take care of converting json to Objects in controller. But my json structure is different then class structure. So I have written my own deserializer. But I am getting problem to accessing values of parent object in JSON. I think it is better to explain my problem using some example -
I have following JSON to deserialize
{
id: 1,
children: {
"name1": "value1",
"name2": "value2"
}
}
I have following classes (Sample Code) -
public class Parent {
private Integer id;
@JsonDeserialize(using= ChildrenDeserializer.class)
private List<Child> children;
//... Getter/setters
}
public class Child {
private Integer id;
private String name;
private String value;
//...getters/setters
}
public class ChildrenDeserializer extends JsonDeserializer<List<Child>> {
@Override
public List<Child> deserialize(JsonParser jsonParser, DeserializationContext ctxt) throws IOException, JsonProcessingException {
List<Child> children = new ArrayList<>();
ObjectCodec oc = jsonParser.getCodec();
JsonNode node = oc.readTree(jsonParser);
Iterator<Map.Entry<String, JsonNode>> fieldsIterator = node.fields();
while (fieldsIterator.hasNext()) {
Map.Entry<String, JsonNode> field = fieldsIterator.next();
String name = field.getKey();
String value = field.getValue().textValue();
Child child = new Child();
//Here I want to get parentId from the Json. Is it possible??
Integer childId = childRepository.searchChildIdByParentId(parentId, name);
child.setId(childId);
child.setName(name);
child.setValue(value);
children.add(child);
}
return children;
}
}
Is there any way to get parentId (which is 1 in above example) while deserializing children??
Having the same need , I come across with your question . My solution to the problem is on the parent constructor: When create the parent class, set the correct property in the child class.
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.testng.Assert;
import org.testng.annotations.Test;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
public class JsonUnitTest {
private static final Logger logger = LogManager.getLogger(JsonUnitTest.class);
@Test
public void unit() {
// test objects
final int parentId = 1;
final int childId = 2;
final ParentClass parent = new ParentClass(parentId);
final ChildClass child = new ChildClass(childId);
parent.setChild(child);
// serialize
final String json = JsonHelper.toJson(parent);
logger.info(json);
logger.info(parent);
// deserialize
final ParentClass newParent = JsonHelper.fromJson(json, ParentClass.class);
// asserts
Assert.assertNotNull(newParent);
Assert.assertEquals(newParent, parent);
}
The result of the test is
[main] INFO JsonUnitTest:29 {"id":1,"child":{"childId":2}}
[main] INFO JsonUnitTest:30 ParentClass [id=1, child=ChildClass [parentId=1, childId=2]]
PASSED: unit
Here the rest of the code :
public static class ParentClass {
public static final String idKey = "id";
public static final String childKey = "child";
@JsonProperty(idKey)
private int id;
@JsonProperty(childKey)
private ChildClass child;
public ParentClass(int id) {
this.id = id;
}
@JsonCreator
public ParentClass(
@JsonProperty(idKey) int id,
@JsonProperty(childKey) ChildClass child) {
super();
this.id = id;
setChild(child);
}
@JsonProperty(idKey)
public int getId() {
return id;
}
@JsonProperty(idKey)
public void setId(int id) {
this.id = id;
}
@JsonProperty(childKey)
public ChildClass getChild() {
return child;
}
@JsonProperty(childKey)
public void setChild(ChildClass child) {
this.child = child;
child.setParentId(id);
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((child == null) ? 0 : child.hashCode());
result = prime * result + id;
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
ParentClass other = (ParentClass) obj;
if (child == null) {
if (other.child != null)
return false;
} else if (!child.equals(other.child))
return false;
if (id != other.id)
return false;
return true;
}
@Override
public String toString() {
return "ParentClass [id=" + id + ", child=" + child + "]";
}
}
public static class ChildClass {
public static final String parentIdKey = "../" + ParentClass.idKey;
public static final String childIdKey = "childId";
private int parentId;
private int childId;
@JsonCreator
public ChildClass(@JsonProperty(childIdKey) int childId) {
super();
this.childId = childId;
}
@JsonIgnore
public int getParentId() {
return parentId;
}
@JsonProperty(parentIdKey)
public void setParentId(int parentId) {
this.parentId = parentId;
}
@JsonProperty(childIdKey)
public int getChildId() {
return childId;
}
@JsonProperty(childIdKey)
public void setChildId(int childId) {
this.childId = childId;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + childId;
result = prime * result + parentId;
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
ChildClass other = (ChildClass) obj;
if (childId != other.childId)
return false;
if (parentId != other.parentId)
return false;
return true;
}
@Override
public String toString() {
return "ChildClass [parentId=" + parentId + ", childId=" + childId + "]";
}
}
}