2012-01-19 33 views
8

Tôi có một JSON như thế nàyJackson: Chuyển đổi tài sản JSON để Object Notation lồng nhau với Dot

{ "id":1, "name":"Jack", "parent.id":2 } 

Lưu ý các dấu chấm trên "parent.id" tài sản

Có thể để lập bản đồ những JSON đến các lớp học sau đây?

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 
} 

Vì vậy, các kết quả lập bản đồ sẽ tương tự như câu sau đây:

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

Child child = new Child(); 
child.setId(1); 
child.setName("Jack"); 
child.setParent(parent); // Here is the result 
+0

Bạn có thể làm điều này bằng cách định nghĩa MessageBodyReader của riêng bạn, nhưng tôi phải tự hỏi tại sao ... ? – Perception

+0

Vì tôi đang sử dụng ExtJS và nó đã gửi JSON với định dạng như trên. –

+2

Chúng tôi có khách hàng Ext.js trong tất cả các giải pháp của chúng tôi. Nhận GUI của dev để sửa mô hình của họ. – Perception

Trả lời

12

bạn có thể chuyển đổi này

{ "id":1, "name":"Jack", "parent.id":2 } 

vào này

{ "id":1, "name":"Jack", "parent": { "id":2 } } 

bằng cách sử dụng

này
// I'm using jQuery here 
$.fn.serializeObject = function() { 
    var arrayData, objectData; 
    arrayData = this.serializeArray(); 
    objectData = {}; 

    $.each(arrayData, function() { 
    var value; 

    if (this.value != null) { 
     value = this.value; 
    } else { 
     value = ''; 
    } 

    // search for "parent.id" like attribute 
    if (this.name.indexOf('.') != -1) { 
     var attrs = this.name.split('.'); 
     var tx = objectData; 

     for (var i = 0; i < attrs.length - 1; i++) { 
     if (objectData[attrs[i]] == undefined) 
      objectData[attrs[i]] = {}; 
     tx = objectData[attrs[i]]; 
     } 
     tx[attrs[attrs.length - 1]] = value; 
    } else { 
     if (objectData[this.name] != null) { 
     if (!objectData[this.name].push) { 
      objectData[this.name] = [objectData[this.name]]; 
     } 

     objectData[this.name].push(value); 
     } else { 
     objectData[this.name] = value; 
     } 
    } 
    }); 

    return objectData; 
}; 

và sau đó bạn có thể tuần tự hóa mã của mình bằng cách sử dụng JSON.serialize().

nếu bạn đang sử dụng Jackson, sau đó bạn có thể deserialize chuỗi yêu cầu JSON bằng cách làm bất kỳ những:

1. Tạo một tùy chỉnh Jackson deserialize mô-đun

2. phân tích cú pháp JSON mình

public Child parseJackson(String jsonRequest) { 
    // what we need 
    ObjectMapper mapper; 
    JsonNode root, parentNode; 

    // your models 
    Child child; 
    Parent parent; 

    // assign 
    mapper = new ObjectMapper(); 
    root = mapper.readTree(jsonRequest); // deserialize JSON as tree 
    parentNode = root.get("parent"); // get the "parent" branch 

    // assign (again) 
    child = mapper.readValue(root, Child.class); 
    parent = mapper.readValue(parentNode, Parent.class); 

    child.setParent(parent); 

    return child; 
} 

Mặt trái của phương pháp này là bạn phải phân tích cú pháp cho mọi JsonRequest đơn lẻ với các đối tượng lồng nhau và sẽ lộn xộn khi thứ Đây là một cấu trúc lồng nhau phức tạp. Nếu đây là một vấn đề, tôi đề nghị bạn làm như # 3

3. tạo ra một tùy chỉnh lớp Jackson ObjectMapper để tự động hóa quá trình này

Ý tưởng là để xây dựng quy trình chung cho # 2 để nó có thể xử lý bất kỳ yêu cầu lồng nhau nào.

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

Nếu bạn đang sử dụng Spring, thì bước cuối cùng sẽ đăng ký lớp này là Spring bean.

<mvc:annotation-driven> 
    <mvc:message-converters> 
     <bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"> 
     <property name="objectMapper"> 
      <bean class="x.y.z.CustomObjectMapper"/> 
     </property> 
     </bean> 
    </mvc:message-converters> 
    </mvc:annotation-driven> 

với những thiết lập bạn có thể dễ dàng sử dụng

@RequestMapping("/saveChild.json") 
@ResponseBody 
public Child saveChild(@RequestBody Child child) { 
    // do something with child 
    return child; 
} 

Hope this helps :)

Các vấn đề liên quan