2012-01-19 3 views
8

나는이잭슨 : 점 표기법으로 중첩 된 객체에 JSON 속성을 변환

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

주처럼 "parent.id"속성

의 점을 JSON 그것을 그 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 
+0

당신은 당신의 자신의 MessageBodyReader을 정의하여이 작업을 수행 할 수 있습니다 :) 도움이되지만 내가 물어 봐야

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

희망을 사용할 수 있습니다 ... 왜 ? – Perception

+0

ExtJS를 사용하고 있기 때문에 위와 같은 형식의 JSON이 전송되었습니다. –

+2

우리는 우리의 모든 솔루션에서 Ext.js 클라이언트를 보유하고 있습니다. GUI를 수정하여 모델을 수정하십시오. – Perception

답변

12

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

에이

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

을 변환 할 수 있습니다이

를 사용하여
// 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; 
}; 

그런 다음 JSON.serialize()을 사용하여 코드를 serialize 할 수 있습니다.

1. 모듈

2. JSON 자신을 구문 분석 정의 잭슨을 역 직렬화 만들기 : 잭슨을 사용하는 경우

, 당신은 다음 중 하나를 수행하여 JSON 요청 문자열을 역 직렬화 할 수 있습니다

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

이 방법의 단점은 중첩 된 객체와 모든 단일 JsonRequest에 대한 구문 분석해야하고 그 때 일 지저분한 것 복잡한 중첩 구조가 있습니다. 이 문제의 경우, 당신은이 과정 아이디어는 일반적인 프로세스를 구축하는 것입니다

을 자동화하는 사용자 정의 잭슨 ObjectMapper 클래스를 생성 # 3

3.을 제안 그래서 처리 할 수 ​​# 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); 
    } 
    } 
} 

그런 다음 마지막 단계는 스프링 빈으로이 클래스를 등록하고, 스프링을 사용하는 경우. 설정이와

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

쉽게이

관련 문제