Java Jackson:使用点表示法将JSON属性转换为嵌套对象

Java Jackson:使用点表示法将JSON属性转换为嵌套对象,java,json,spring,jackson,Java,Json,Spring,Jackson,我有一个类似这样的JSON { "id":1, "name":"Jack", "parent.id":2 } 注意“parent.id”属性上的点 是否可以将这些JSON映射到以下类 class Child { private int id; private String name; private Parent parent; //getter and setter methods } class Parent { private int id;

我有一个类似这样的JSON

{ "id":1, "name":"Jack", "parent.id":2 }
注意“parent.id”属性上的点

是否可以将这些JSON映射到以下类

class Child {
    private int id;
    private String name;

    private Parent parent;

    //getter and setter methods
}

class Parent {
    private int id;
    private String name;

    //getter and setter methods
}
因此,映射结果将类似于以下语句:

Parent parent = new Parent();
parent.setId(2);

Child child = new Child();
child.setId(1);
child.setName("Jack");
child.setParent(parent); // Here is the result
你可以转换这个

{“id”:1,“name”:“Jack”,“parent.id”:2}
进入这个

{“id”:1,“name”:“Jack”,“parent”:{“id”:2}
用这个

//我在这里使用jQuery
$.fn.serializeObject=函数(){
var arrayData,objectData;
arrayData=this.serializeArray();
objectData={};
$.each(数组数据,函数(){
var值;
如果(this.value!=null){
value=this.value;
}否则{
值=“”;
}
//搜索类似“parent.id”的属性
if(this.name.indexOf('.')!=-1){
var attrs=this.name.split('.');
var tx=对象数据;
对于(变量i=0;i
然后可以使用
JSON.serialize()
对代码进行序列化

如果您使用的是Jackson,则可以通过执行以下任一操作来反序列化JSON请求字符串:

1。创建自定义Jackson反序列化模块

2。自己解析JSON

public子进程(字符串jsonRequest){
//我们需要什么
对象映射器映射器;
JsonNode根,parentNode;
//你的模型
儿童;
父母;
//分配
映射器=新的ObjectMapper();
root=mapper.readTree(jsonRequest);//将JSON反序列化为树
parentNode=root.get(“parent”);//获取“parent”分支
//分配(再次)
child=mapper.readValue(根,child.class);
parent=mapper.readValue(parentNode,parent.class);
setParent(家长);
返回儿童;
}
这种方法的缺点是您必须使用嵌套对象解析每个单独的JsonRequest,当存在复杂的嵌套结构时,这种方法会很混乱。如果这是一个问题,我建议你做#3

3。创建自定义Jackson ObjectMapper类以自动化此过程

其想法是为#2构建通用流程,以便它能够处理任何嵌套请求

public class CustomObjectMapper extends ObjectMapper {

  // here's the method you need
  @Override
  public <T> T readValue(String src, Class<T> type)
      throws IOException, JsonParseException, JsonMappingException {

    JsonNode root = this.readTree(src);
    try {
      return readNestedValue(root, type);
    } catch (InstantiationException | IllegalAccessException | IOException
        | IllegalArgumentException | InvocationTargetException e) {
      return super.readValue(src, type);
    }

  }

  // if you're using Spring, I suggest you implement this method as well
  // since Spring's MappingJacksonHttpMessageConverter class will call 
  // this method.
  @Override
  public <T> T readValue(InputStream src, JavaType type)
      throws IOException, JsonParseException, JsonMappingException {

    JsonNode root = this.readTree(src);
    try {
      return readNestedValue(root, (Class<T>) type.getRawClass());
    } catch (InstantiationException | IllegalAccessException | IOException
        | IllegalArgumentException | InvocationTargetException e) {
      return super.readValue(src, type);
    }

  }

  // we need this to recursively scan the tree node
  protected <T> T readNestedValue(JsonNode root, Class<T> type)
      throws InstantiationException, IllegalAccessException, IOException,
        IllegalArgumentException, InvocationTargetException {

    // initialize the object use ObjectMapper's readValue
    T obj = super.readValue(root, type);
    Iterator it = root.getFieldNames();
    while (it.hasNext()) {
      String name = (String) it.next();
      String camelCaseName = name.substring(0, 1).toUpperCase() + name.substring(1);
      JsonNode node = root.get(name);

      Field f;
      try {
        f = type.getDeclaredField(name);
      } catch (NoSuchFieldException e) {
        f = findFieldInSuperClass(name, type.getSuperclass());
      }
      // if no field found then ignore
      if (f == null) continue; 

      Method getter, setter;
      try {
        getter = type.getMethod("get" + camelCaseName);
      } catch (NoSuchMethodException e) {
        getter = findGetterInSuperClass("get" + camelCaseName, type.getSuperclass());
      }
      // if no getter found or it has been assigned then ignore
      if (getter == null || getter.invoke(obj) != null) continue;

      try {
        setter = type.getMethod("set" + camelCaseName);
      } catch (NoSuchMethodException ex) {
        setter = findSetterInSuperClass("set" + camelCaseName, type.getSuperclass(), f.getType());
      }
      // if no setter found then ignore
      if (setter == null) continue;

      setter.invoke(obj, readNestedValue(node, f.getType()));
    }

    return obj;
  }

  // we need this to search for field in super class
  // since type.getDeclaredField() will only return fields that in the class
  // but not super class
  protected Field findFieldInSuperClass(String name, Class sClass) {
    if (sClass == null) return null;
    try {
      Field f = sClass.getDeclaredField(name);
      return f;
    } catch (NoSuchFieldException e) {
      return findFieldInSuperClass(name, sClass.getSuperclass());
    }
  }

  protected Method findGetterInSuperClass(String name, Class sClass) {
    if (sClass == null) return null;
    try {
      Method m = sClass.getMethod(name);
      return m;
    } catch (NoSuchMethodException e) {
      return findGetterInSuperClass(name, sClass.getSuperclass());
    }
  }

  protected Method findSetterInSuperClass(String name, Class sClass, Class type) {
    if (sClass == null) return null;
    try {
      Method m = sClass.getMethod(name, type);
      return m;
    } catch (NoSuchMethodException e) {
      return findSetterInSuperClass(name, sClass.getSuperclass(), type);
    }
  }
}

希望这有帮助:)

您可以通过定义自己的MessageBodyReader来做到这一点,但我必须问一下。。。为什么?因为我使用的是ExtJS,它发送的JSON格式如上所述。我们所有的解决方案中都有Ext.js客户端。让GUI开发人员修复他们的模型。
@RequestMapping("/saveChild.json")
@ResponseBody
public Child saveChild(@RequestBody Child child) {
  // do something with child
  return child;
}