Jackson은 캐스팅하지 않고 JsonNode를 ArrayNode로 변환하는 방법은 무엇입니까?


116

JSON 라이브러리를 org.json에서 Jackson으로 변경하고 있으며 다음 코드를 마이그레이션하고 싶습니다.

JSONObject datasets = readJSON(new URL(DATASETS));
JSONArray datasetArray =  datasets.getJSONArray("datasets");

이제 Jackson에는 다음이 있습니다.

ObjectMapper m = new ObjectMapper();
JsonNode datasets = m.readTree(new URL(DATASETS));      
ArrayNode datasetArray = (ArrayNode)datasets.get("datasets");

그러나 나는 캐스트가 마음에 들지 않습니다. 가능성이 ClassCastException있습니까? 배열이 아닌 경우 적절한 오류 처리를 할 수 있도록 getJSONArrayin에 해당하는 메서드 org.json가 있습니까?


불행히도 데이터가 필드 이름을 고정하지 않기 때문에 전체 매핑을 사용할 수 없습니다.
Konrad Höffner 2013 년

1
필드 이름이 제한된 집합에서 나온 경우 모든 기능을 갖춘 클래스를 정의하고 deserializer의 FAIL_ON_UNKNOWN_PROPERTIES기능을 사용하여 사용되지 않는 필드에서 반환되는 null을 가져올 수 있습니다. 그러나 이것은 물론 필드 이름 세트가 상대적으로 제한된 경우에만 옵션입니다.
fvu

이 솔루션이 제 경우에 가장 적합하지 않다고 생각하지만 미리 알려진 제한된 세트에 문제가 생길 경우를 대비하여 기억할 것입니다!
Konrad Höffner 2013 년

답변:


247

예, Jackson 수동 파서 디자인은 다른 라이브러리와 상당히 다릅니다. 특히, JsonNode일반적으로 다른 API의 배열 노드와 연결하는 대부분의 함수가 있음을 알 수 있습니다. 따라서 ArrayNode사용 하기 위해 캐스트 할 필요가 없습니다 . 예를 들면 다음과 같습니다.

JSON :

{
    "objects" : ["One", "Two", "Three"]
}

암호:

final String json = "{\"objects\" : [\"One\", \"Two\", \"Three\"]}";

final JsonNode arrNode = new ObjectMapper().readTree(json).get("objects");
if (arrNode.isArray()) {
    for (final JsonNode objNode : arrNode) {
        System.out.println(objNode);
    }
}

산출:

"하나"
"둘"
"셋"

isArray반복하기 전에 노드가 실제로 배열인지 확인하기 위해 의 사용에 유의하십시오 . 데이터 구조에 대해 절대적으로 확신하는 경우 검사는 필요하지 않지만 필요한 경우 사용할 수 있습니다 (대부분의 다른 JSON 라이브러리와 다르지 않음).


2
당신은 저에게 시간을 절약했습니다. 감사!
Igor Morais

"for (final JsonNode objNode : arrNode)"행에 "final"이 사용 된 이유를 알 수 있습니까?
Anthony Vinay

5

Java 8에서는 다음과 같이 할 수 있습니다.

import java.util.*;
import java.util.stream.*;

List<JsonNode> datasets = StreamSupport
    .stream(datasets.get("datasets").spliterator(), false)
    .collect(Collectors.toList())

1

org.json에 getJSONArray에 해당하는 메서드가 있으므로 배열이 아닌 경우 적절한 오류 처리가 가능합니까?

귀하의 입력에 따라 다릅니다. 즉, URL에서 가져온 항목입니다. "datasets"속성의 값이 일반 배열이 아닌 연관 배열이면 ClassCastException.

그러나 다시 말하지만, 이전 버전의 정확성 입력에 따라 다릅니다. 새 버전이를 던지는 상황에서는 ClassCastException이전 버전이 JSONException. 참조 : http://www.json.org/javadoc/org/json/JSONObject.html#getJSONArray(java.lang.String)


아 좋아요, ClassCastException을 잡을 수 있습니다. 감사합니다! 내 취향에 따라 특정 JsonException을 갖는 것보다 약간 덜 우아하지만 그렇지 않으면 가능하지 않으면 여전히 좋습니다.
Konrad Höffner 2013 년

0

하루가 끝날 때 반복하여 ArrayNode의 데이터를 소비하고 싶다고 가정합니다. 그에 대한:

Iterator<JsonNode> iterator = datasets.withArray("datasets").elements();
while (iterator.hasNext()) 
        System.out.print(iterator.next().toString() + " "); 

또는 스트림 및 람다 함수를 사용하는 경우 :

import com.google.common.collect.Streams;
Streams.stream(datasets.withArray("datasets").elements())
    .forEach( item -> System.out.print(item.toString()) )
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.