2017-09-19 3 views
1

하기 위해 잭슨에게하는하지만 난 두 개의 층을 풀다 하는 방법에 대한 예를 찾을 수있는 방법.내가</em> 잭슨의 <code>Object</code> 포장을 푸는 <em>하는 방법을 알고 하위 요소 최상위 요소

셰어 API 엔드 포인트는 다음과 같은 형식으로 모든 것을 반환 :

{ 
    "d": { 
     "results": [ 
      { 
       /* lots objects with lots of properties 
        that are irrelevant to the question */ 
      } 
     ] 
    } 
} 

나는 다음과가 results 값 최고 수준의 객체가되지 않습니다했습니다. 나는 사용자 정의 디시리얼라이저를 작성하지 않고도 사용자 지정 개체 계층 구조 및 을 만들 필요없이 최상위 Array로하여 results를 분석 시작 Jackson을 어떻게 알 수 있습니까

this.om.readerFor(new TypeReference<List<User>>() {}) 
     .withRootName("d") 
     .readValue(response.parseAsString()); 

. 이 항목이 채워지는 주석이 달린 사용자 지정 개체가 있는데 TypeSafety이므로 Map<String,Object>은 내가 원하는 것이 아닙니다.

답변

2

아마 아닐 가장 효율적인 방법하지만, 먼저 나무로 개체를 구문 분석하고 당신이 필요로하는 노드로 이동 시도 할 수 있습니다. 이런 식으로 뭔가 : 쉽게

mapper.readerFor(new TypeReference<List<User>>() {}).readValue(mapper.readTree(json).get("d").get("results"))‌​; 

읽을 :

mapper.convertValue(mapper.readTree(json).get("d").get("‌​results"), new TypeReference<List<User>>() {}); 
+0

이 솔루션을 독자적으로 변형 한 것은 내가 원하는 것을 얻는 최선의 방법이라고 생각합니다. –

+1

* 능률적 인 *에 관해서는, 어쨌든 한번 구문 분석해야하므로 변환을 시작하기 위해'JsonNode'를 전달하는 것이 의미있는 방식으로 덜 효율적이지는 않습니다. 이것은 정상적으로 무엇을하지만, 두 가지 명백한 단계에 있습니다. 'space' 나'time'에서 매우 효율적이라면''Json''을 사용하지 않을 것입니다. –

+1

@JarrodRoberson 예, 성능은별로 중요하지 않다고 생각합니다. 사실 저는 항상 성능을 테스트 한적이 없으며 항상 다른 사람들의 말에 의존합니다. 그리고 기본 테스트 후 : https://gist.github.com/varren/3b7468a1d7abadad4958fe6bd7d42d44#file-main-java-L153-L178'time' 포인트에서 보면 나쁘지는 않지만 단순한 경우에 비해 2 배 느려질 수 있습니다. 사용자의 1 필드는 복잡한 json의 경우 30 % 더 느립니다. 스페이스 포인트 (space point)로부터도 https://i.stack.imgur.com/bftGe.png의 효율성이 거의 2 배 정도 낮아졌으며, 래퍼 오브젝트 나 커스텀 데스티메이터 또는 인라인'JsonParser' – varren

-1
@JsonRootName("d") 
class Data { 
    public Map<String, Object>[] results; 
} 

ObjectMapper mapper = new ObjectMapper(); 
mapper.enable(SerializationFeature.WRAP_ROOT_VALUE); 
mapper.enable(DeserializationFeature.UNWRAP_ROOT_VALUE); 

Map<String, Object> results = new LinkedHashMap<>(); 
results.put("key1", "val1"); 
results.put("key2", "val2"); 

Data expected = new Data(); 
expected.results = new Map[1]; 
expected.results[0] = results; 

String json = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(expected); 
Data actual = mapper.readerFor(Data.class).readValue(json); 

JSON 문자열은 다음과 같습니다

{ 
    "d" : { 
    "results" : [ { 
     "key1" : "val1", 
     "key2" : "val2" 
    } ] 
    } 
} 

P.S.을 당신이 concreate object에 신경 쓰지 않고 Map<String, Object>이 좋다면, 다음과 같이 사용할 수 있습니다.

Map<String, Object> results = (Map<String, Object>)((List<?>)mapper.readerFor(Map.class).<Map<String, Map<String, ?>>>readValues(json).next().get("d").get("results")).get(0); 
+1

* "객체 계층 구조를 만들 필요없이이"* - 난에 명시된 바와 같이 나는이에 대한 특별한 클래스를 가지고 싶지 않아 질문. –

+0

Map 결과 = (Map ) (목록 )와 같이 구체 객체와 Map 에 신경 쓰지 않는다면 다음과 같이 할 수 있다고 생각합니다. mapper.readerFor (Map.class). >> readValues ​​(json) .next(). get ("d"). get ("results")). –