source

org.json을 효율적으로 매핑하는 방법.JSONObject to POJO?

gigabyte 2023. 2. 14. 21:26
반응형

org.json을 효율적으로 매핑하는 방법.JSONObject to POJO?

서드파티 라이브러리를 사용하여 JSON 형식의 데이터를 가져오고 있습니다.도서관은 나에게 데이터를 제공한다.org.json.JSONObject이 맵을 만들고 싶다.JSONObjectPOJO(Plain Old Java Object)로 변환하여 액세스/코드를 심플하게 합니다.

매핑에는 현재ObjectMapper다음 방법으로 잭슨 도서관에서 가져옵니다.

JSONObject jsonObject = //...
ObjectMapper mapper = new ObjectMapper();
MyPojoClass myPojo = mapper.readValue(jsonObject.toString(), MyPojoClass.class);

제가 이해하기로는, 위의 코드는 상당히 최적화될 수 있습니다. 왜냐하면 현재 데이터에는JSONObject는, 이미 해석되고 있는 것으로, 를 사용해 시리얼라이제이션-디시리얼라이제이션 체인에 다시 보내집니다.JSONObject.toString()method에 이어서ObjectMapper.

이러한 2개의 변환을 피하고 싶다(toString()및 해석).를 사용할 수 있는 방법이 있습니까?JSONObject데이터를 POJO에 직접 매핑할 수 있을까요?

일부 JSON 데이터(개체)를 추상적으로 표현하고 JSON 데이터()com.fasterxml.jackson.databind.JsonNode를 추상적으로 표현한 Jackson 라이브러리를 사용할 예정이기 때문에 하나의 표현에서 다른 표현으로 변환하면 구문 분석-직렬화-파스 프로세스에서 벗어날 수 있습니다.그래서, 그 대신,readValue받아들이는 방법String, 버전을 사용하고,JsonParser:

JSONObject jsonObject = //...
JsonNode jsonNode = convertJsonFormat(jsonObject);
ObjectMapper mapper = new ObjectMapper();
MyPojoClass myPojo = mapper.readValue(new TreeTraversingParser(jsonNode), MyPojoClass.class);

JSON은 매우 단순한 형식이기 때문에 쉽게 작성할 수 있습니다.convertJsonFormat손으로.제 시도는 이렇습니다.

static JsonNode convertJsonFormat(JSONObject json) {
    ObjectNode ret = JsonNodeFactory.instance.objectNode();

    @SuppressWarnings("unchecked")
    Iterator<String> iterator = json.keys();
    for (; iterator.hasNext();) {
        String key = iterator.next();
        Object value;
        try {
            value = json.get(key);
        } catch (JSONException e) {
            throw new RuntimeException(e);
        }
        if (json.isNull(key))
            ret.putNull(key);
        else if (value instanceof String)
            ret.put(key, (String) value);
        else if (value instanceof Integer)
            ret.put(key, (Integer) value);
        else if (value instanceof Long)
            ret.put(key, (Long) value);
        else if (value instanceof Double)
            ret.put(key, (Double) value);
        else if (value instanceof Boolean)
            ret.put(key, (Boolean) value);
        else if (value instanceof JSONObject)
            ret.put(key, convertJsonFormat((JSONObject) value));
        else if (value instanceof JSONArray)
            ret.put(key, convertJsonFormat((JSONArray) value));
        else
            throw new RuntimeException("not prepared for converting instance of class " + value.getClass());
    }
    return ret;
}

static JsonNode convertJsonFormat(JSONArray json) {
    ArrayNode ret = JsonNodeFactory.instance.arrayNode();
    for (int i = 0; i < json.length(); i++) {
        Object value;
        try {
            value = json.get(i);
        } catch (JSONException e) {
            throw new RuntimeException(e);
        }
        if (json.isNull(i))
            ret.addNull();
        else if (value instanceof String)
            ret.add((String) value);
        else if (value instanceof Integer)
            ret.add((Integer) value);
        else if (value instanceof Long)
            ret.add((Long) value);
        else if (value instanceof Double)
            ret.add((Double) value);
        else if (value instanceof Boolean)
            ret.add((Boolean) value);
        else if (value instanceof JSONObject)
            ret.add(convertJsonFormat((JSONObject) value));
        else if (value instanceof JSONArray)
            ret.add(convertJsonFormat((JSONArray) value));
        else
            throw new RuntimeException("not prepared for converting instance of class " + value.getClass());
    }
    return ret;
}

알아둬, 잭슨의 가족은JsonNode몇 가지 추가 유형을 나타낼 수 있습니다(예:BigInteger,Decimal, 등) 위의 코드가 다음 사항을 모두 커버하기 때문에 이러한 기능은 필요하지 않습니다.JSONObject를 나타낼 수 있습니다.

오래된 질문에 답을 덧붙이긴 하지만...

Jackson은 org.json 타입과 바인드 할 수 있습니다.일반적으로 JSON에 대한 효과적인 직렬화 및 역직렬화를 통해 바인딩할 수 있는 모든 유형 간에 변환할 수 있습니다.

JsonOrgModule을 등록한 경우 ObjectMapper에서 직접 변환할 수 있습니다.

@Test
public void convert_from_jsonobject() throws Exception {
    JSONObject obj = new JSONObject().put("value", 3.14);
    ObjectMapper mapper = new ObjectMapper().registerModule(new JsonOrgModule());
    PojoData data = mapper.convertValue(obj, PojoData.class);
    assertThat(data.value, equalTo(3.14));
}

@Test
public void convert_to_jsonobject() throws Exception {
    PojoData data = new PojoData();
    data.value = 3.14;
    ObjectMapper mapper = new ObjectMapper().registerModule(new JsonOrgModule());
    JSONObject obj = mapper.convertValue(data, JSONObject.class);
    assertThat(obj.getDouble("value"), equalTo(3.14));
}

public static final class PojoData {
    public double value;
}

이게 효과적으로 연재되고 있다고 말씀드렸잖아요?맞습니다. 입력 객체를 토큰 버퍼로 직렬화합니다. 토큰 버퍼는 JSON 구문 분석 이벤트의 스트림을 나타내지만 입력 데이터를 주로 참조할 수 있기 때문에 문자열 구축 등의 영향은 적습니다.그런 다음 이 스트림을 역직렬라이저에 공급하여 출력 객체를 생성합니다.

JSONObject를 JsonNode로 변환하는 제안과 비슷하지만 훨씬 더 일반적입니다.JsonNode를 중간 또는 토큰버퍼로 구성해도 오버헤드가 발생하지 않습니다.

Jackson과 관련이 없다면 편리한 Google-gson 라이브러리를 대안으로 사용할 수 있습니다.1개의 항아리만 필요하며 사용법은 매우 간단합니다.

Java 개체를 JSON 문자열로 변환하려면 다음 절차를 수행합니다.

  String json_string = new Gson().toJson(an_object);

JSON 문자열에서 Java 객체 생성:

  MyObject obj = new Gson().fromJson(a_json_string, MyObject.class);

잭슨과 비교해서 퍼포먼스는 잘 모르겠지만, 이것보다 더 간단하기는 어렵지만...Gson은 안정적이고 널리 사용되는 도서관입니다.

https://code.google.com/p/google-gson/ 를 참조해 주세요.

Gson을 사용하여 보다 간단한 방법.

JSONObject jsonObject = //...

PojoObject objPojo = new Gson().fromJson(jsonObject.toString(), PojoObject.class);

이건 나한테 효과가 있었어.

언급URL : https://stackoverflow.com/questions/20534862/how-to-efficiently-map-a-org-json-jsonobject-to-a-pojo

반응형