Json Deserializer - 如何从父 JSON 对象获取数据

Gau*_*pta 5 java spring jackson json-deserialization

我正在使用 Spring MVC,spring 负责将 json 转换为控制器中的对象。但是我的 json 结构与类结构不同。所以我写了自己的解串器。但是我在 JSON 中访问父对象的值时遇到问题。我认为最好用一些例子来解释我的问题 -

我有以下 JSON 来反序列化

{
  id: 1,
  children: {
    "name1": "value1",
    "name2": "value2"
  }
}
Run Code Online (Sandbox Code Playgroud)

我有以下课程(示例代码)-

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

有没有办法在反序列化孩子的同时获得 parentId (在上面的例子中是 1 )?

小智 0

有同样的需求,我遇到了你的问题。我的解决方案是在父类构造函数上:创建父类时,在子类中设置正确的属性。

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);

   }
Run Code Online (Sandbox Code Playgroud)

测试结果是

[main] INFO JsonUnitTest:29 {"id":1,"child":{"childId":2}}
[main] INFO JsonUnitTest:30 ParentClass [id=1, child=ChildClass [parentId=1, childId=2]]
PASSED: unit
Run Code Online (Sandbox Code Playgroud)

这里是其余的代码:

   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 + "]";
      }
   }
}
Run Code Online (Sandbox Code Playgroud)