Java에서 JSON을 유창하게 빌드하는 방법은 무엇입니까?


107

나는 다음과 같은 것을 생각하고 있습니다.

String json = new JsonBuilder()
  .add("key1", "value1")
  .add("key2", "value2")
  .add("key3", new JsonBuilder()
    .add("innerKey1", "value3"))
  .toJson();

이런 종류의 유창한 건물에 가장 적합한 Java JSON 라이브러리는 무엇입니까?

업데이트 : 나는 GSON을 포장하고 ... 거의 원하는 결과를 가지고 하나 개의 장애로 .


1
나는 그 스타일을 따르는 JSON 라이브러리를 본 적이 없다고 생각합니다. 기존 라이브러리를 확장하여 원하는 작업을 수행 할 수 있습니까?
aroth

1
@aroth-우리가 말하는 동안 com.google.gson 주위에 래퍼를 작성하고 있습니다.
ripper234


1
지도 및 목록의 적절한 "중첩"을 구성하고 직렬화합니다. "장쇄 폴리머"문구는 피하십시오.
Hot Licks

답변:


141

org.json을 사용하고 있습니다. 라이브러리를 있으며 친절하고 친절하다는 것을 알았습니다.

예:

String jsonString = new JSONObject()
                  .put("JSON1", "Hello World!")
                  .put("JSON2", "Hello my World!")
                  .put("JSON3", new JSONObject().put("key1", "value1"))
                  .toString();

System.out.println(jsonString);

산출:

{"JSON2":"Hello my World!","JSON3":{"key1":"value1"},"JSON1":"Hello World!"}

15
이것은 그다지 유창하지 않습니다.
Vlad

제공 한 웹이 더 이상 작동하지 않습니다. 업데이트 해 주시겠습니까?
Saša Zejnilović

13
@Vlad-이것은 유창한 건축업자들이 나에게 제안한 것입니다. 더 낫다고 생각하는 설정의 예를 제공 할 수 있습니까?
scubbo

3
이것은 여전히 ​​더 깨끗한 옵션입니다. 그것은 자바는 여전히 2020 년에 JSON 구문 분석 / 빌드에 가장 적합한 옵션을 파악 일시 정지해야 DEVS 있다는 말도 안돼
mtyson

113

Java EE 7 Json 사양을 참조하십시오 . 이것이 올바른 방법입니다.

String json = Json.createObjectBuilder()
            .add("key1", "value1")
            .add("key2", "value2")
            .build()
            .toString();

8
이것은 javax.jsonJava 7 이상의 일부이므로 2015 년에 정답으로 표시되어야합니다 .
Sridhar Sarnobat 2015

42
Java SE가 아닌 Java EE API입니다.
igorp1024 2015

javax.json API의 String 객체에서 JsonString 객체를 만드는 방법에 대한 아이디어가 있습니까?
레이몬드


12
메이븐 의존성 유일한에 대한 javax.json패키지는 이 한
장 발장

12

최근에 Gson 객체를 유창하게 만들기위한 라이브러리를 만들었습니다.

http://jglue.org/fluent-json/

다음과 같이 작동합니다.

  JsonObject jsonObject = JsonBuilderFactory.buildObject() //Create a new builder for an object
  .addNull("nullKey")                            //1. Add a null to the object

  .add("stringKey", "Hello")                     //2. Add a string to the object
  .add("stringNullKey", (String) null)           //3. Add a null string to the object

  .add("numberKey", 2)                           //4. Add a number to the object
  .add("numberNullKey", (Float) null)            //5. Add a null number to the object

  .add("booleanKey", true)                       //6. Add a boolean to the object
  .add("booleanNullKey", (Boolean) null)         //7. Add a null boolean to the object

  .add("characterKey", 'c')                      //8. Add a character to the object
  .add("characterNullKey", (Character) null)     //9. Add a null character to the object

  .addObject("objKey")                           //10. Add a nested object
    .add("nestedPropertyKey", 4)                 //11. Add a nested property to the nested object
    .end()                                       //12. End nested object and return to the parent builder

  .addArray("arrayKey")                          //13. Add an array to the object
    .addObject()                                 //14. Add a nested object to the array
      .end()                                     //15. End the nested object
    .add("arrayElement")                         //16. Add a string to the array
    .end()                                       //17. End the array

    .getJson();                                  //Get the JsonObject

String json = jsonObject.toString();

제네릭의 마법을 통해 속성 키가있는 배열에 요소를 추가하거나 속성 이름이없는 개체에 요소를 추가하려고하면 컴파일 오류가 발생합니다.

JsonObject jsonArray = JsonBuilderFactory.buildArray().addObject().end().add("foo", "bar").getJson(); //Error: tried to add a string with property key to array.
JsonObject jsonObject = JsonBuilderFactory.buildObject().addArray().end().add("foo").getJson(); //Error: tried to add a string without property key to an object.
JsonArray jsonArray = JsonBuilderFactory.buildObject().addArray("foo").getJson(); //Error: tried to assign an object to an array.
JsonObject jsonObject = JsonBuilderFactory.buildArray().addObject().getJson(); //Error: tried to assign an object to an array.

마지막으로 도메인 개체를 JSON에 매핑 할 수있는 매핑 지원이 API에 있습니다. 목표는 Java8이 출시되면 다음과 같이 할 수 있습니다.

Collection<User> users = ...;
JsonArray jsonArray = JsonBuilderFactory.buildArray(users, { u-> buildObject()
                                                                 .add("userName", u.getName())
                                                                 .add("ageInYears", u.getAge()) })
                                                                 .getJson();

8

Jackson을 사용하여 많은 JsonNode코드를 작성하는 경우 다음 유틸리티 세트에 흥미로울 수 있습니다. 이를 사용하는 이점은 생성중인 JSON의 구조를 더 잘 보여주는보다 자연스러운 체인 스타일을 지원한다는 것입니다.

다음은 사용 예입니다.

import static JsonNodeBuilders.array;
import static JsonNodeBuilders.object;

...

val request = object("x", "1").with("y", array(object("z", "2"))).end();

다음 JSON과 동일합니다.

{"x":"1", "y": [{"z": "2"}]}

수업은 다음과 같습니다.

import static lombok.AccessLevel.PRIVATE;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.JsonNodeFactory;
import com.fasterxml.jackson.databind.node.ObjectNode;

import lombok.NoArgsConstructor;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import lombok.val;

/**
 * Convenience {@link JsonNode} builder.
 */
@NoArgsConstructor(access = PRIVATE)
public final class JsonNodeBuilders {

  /**
   * Factory methods for an {@link ObjectNode} builder.
   */

  public static ObjectNodeBuilder object() {
    return object(JsonNodeFactory.instance);
  }

  public static ObjectNodeBuilder object(@NonNull String k1, boolean v1) {
    return object().with(k1, v1);
  }

  public static ObjectNodeBuilder object(@NonNull String k1, int v1) {
    return object().with(k1, v1);
  }

  public static ObjectNodeBuilder object(@NonNull String k1, float v1) {
    return object().with(k1, v1);
  }

  public static ObjectNodeBuilder object(@NonNull String k1, String v1) {
    return object().with(k1, v1);
  }

  public static ObjectNodeBuilder object(@NonNull String k1, String v1, @NonNull String k2, String v2) {
    return object(k1, v1).with(k2, v2);
  }

  public static ObjectNodeBuilder object(@NonNull String k1, String v1, @NonNull String k2, String v2,
      @NonNull String k3, String v3) {
    return object(k1, v1, k2, v2).with(k3, v3);
  }

  public static ObjectNodeBuilder object(@NonNull String k1, JsonNodeBuilder<?> builder) {
    return object().with(k1, builder);
  }

  public static ObjectNodeBuilder object(JsonNodeFactory factory) {
    return new ObjectNodeBuilder(factory);
  }

  /**
   * Factory methods for an {@link ArrayNode} builder.
   */

  public static ArrayNodeBuilder array() {
    return array(JsonNodeFactory.instance);
  }

  public static ArrayNodeBuilder array(@NonNull boolean... values) {
    return array().with(values);
  }

  public static ArrayNodeBuilder array(@NonNull int... values) {
    return array().with(values);
  }

  public static ArrayNodeBuilder array(@NonNull String... values) {
    return array().with(values);
  }

  public static ArrayNodeBuilder array(@NonNull JsonNodeBuilder<?>... builders) {
    return array().with(builders);
  }

  public static ArrayNodeBuilder array(JsonNodeFactory factory) {
    return new ArrayNodeBuilder(factory);
  }

  public interface JsonNodeBuilder<T extends JsonNode> {

    /**
     * Construct and return the {@link JsonNode} instance.
     */
    T end();

  }

  @RequiredArgsConstructor
  private static abstract class AbstractNodeBuilder<T extends JsonNode> implements JsonNodeBuilder<T> {

    /**
     * The source of values.
     */
    @NonNull
    protected final JsonNodeFactory factory;

    /**
     * The value under construction.
     */
    @NonNull
    protected final T node;

    /**
     * Returns a valid JSON string, so long as {@code POJONode}s not used.
     */
    @Override
    public String toString() {
      return node.toString();
    }

  }

  public final static class ObjectNodeBuilder extends AbstractNodeBuilder<ObjectNode> {

    private ObjectNodeBuilder(JsonNodeFactory factory) {
      super(factory, factory.objectNode());
    }

    public ObjectNodeBuilder withNull(@NonNull String field) {
      return with(field, factory.nullNode());
    }

    public ObjectNodeBuilder with(@NonNull String field, int value) {
      return with(field, factory.numberNode(value));
    }

    public ObjectNodeBuilder with(@NonNull String field, float value) {
      return with(field, factory.numberNode(value));
    }

    public ObjectNodeBuilder with(@NonNull String field, boolean value) {
      return with(field, factory.booleanNode(value));
    }

    public ObjectNodeBuilder with(@NonNull String field, String value) {
      return with(field, factory.textNode(value));
    }

    public ObjectNodeBuilder with(@NonNull String field, JsonNode value) {
      node.set(field, value);
      return this;
    }

    public ObjectNodeBuilder with(@NonNull String field, @NonNull JsonNodeBuilder<?> builder) {
      return with(field, builder.end());
    }

    public ObjectNodeBuilder withPOJO(@NonNull String field, @NonNull Object pojo) {
      return with(field, factory.pojoNode(pojo));
    }

    @Override
    public ObjectNode end() {
      return node;
    }

  }

  public final static class ArrayNodeBuilder extends AbstractNodeBuilder<ArrayNode> {

    private ArrayNodeBuilder(JsonNodeFactory factory) {
      super(factory, factory.arrayNode());
    }

    public ArrayNodeBuilder with(boolean value) {
      node.add(value);
      return this;
    }

    public ArrayNodeBuilder with(@NonNull boolean... values) {
      for (val value : values)
        with(value);
      return this;
    }

    public ArrayNodeBuilder with(int value) {
      node.add(value);
      return this;
    }

    public ArrayNodeBuilder with(@NonNull int... values) {
      for (val value : values)
        with(value);
      return this;
    }

    public ArrayNodeBuilder with(float value) {
      node.add(value);
      return this;
    }

    public ArrayNodeBuilder with(String value) {
      node.add(value);
      return this;
    }

    public ArrayNodeBuilder with(@NonNull String... values) {
      for (val value : values)
        with(value);
      return this;
    }

    public ArrayNodeBuilder with(@NonNull Iterable<String> values) {
      for (val value : values)
        with(value);
      return this;
    }

    public ArrayNodeBuilder with(JsonNode value) {
      node.add(value);
      return this;
    }

    public ArrayNodeBuilder with(@NonNull JsonNode... values) {
      for (val value : values)
        with(value);
      return this;
    }

    public ArrayNodeBuilder with(JsonNodeBuilder<?> value) {
      return with(value.end());
    }

    public ArrayNodeBuilder with(@NonNull JsonNodeBuilder<?>... builders) {
      for (val builder : builders)
        with(builder);
      return this;
    }

    @Override
    public ArrayNode end() {
      return node;
    }

  }

}

구현은 Lombok을 사용 하지만 Java 상용구를 채우기 위해 쉽게 탈당 할 수 있습니다.


2
String json = new JsonBuilder(new GsonAdapter())
  .object("key1", "value1")
  .object("key2", "value2")
  .object("key3")
    .object("innerKey1", "value3")
    .build().toString();

위의 솔루션이 우아하다고 생각되면 JsonBuilder lib 를 사용해보십시오 . 많은 유형의 Json 라이브러리에 대한 json 구조를 빌드하는 한 가지 방법을 허용하기 위해 만들어졌습니다. 현재 구현에는 Gson, Jackson 및 MongoDB가 포함됩니다. 즉. 잭슨은 그냥 스왑 :

String json = new JsonBuilder(new JacksonAdapter()).

요청하면 기꺼이 다른 사람을 추가 할 수 있고, 직접 구현하는 것도 매우 쉽습니다.


불행히도 현재 maven central에 없습니다. github.com/HknL/JsonBuilder/issues/8
dschulten

1

아마도 json-lib를 얻고 싶을 것 같습니다.

http://json-lib.sourceforge.net/

Douglas Crockford는 JSON을 발명 한 사람입니다. 그의 Java 라이브러리는 다음과 같습니다.

http://www.json.org/java/

json-lib의 사람들이 Crockford가 그만 둔 곳에서 집어 들었던 것 같습니다. 둘 다 JSON을 완벽하게 지원하며, 둘 다 JSONObject, JSONArray 및 JSONFunction 구문을 사용합니다 (내가 말할 수있는 한 호환 가능).

'도움이 되길 ..


유창한 구문을 지원합니까?
ripper234


0

직접 작성하는 것이 생각보다 훨씬 쉽습니다 JsonElementInterface. 메서드와 함께 인터페이스를 사용하고 해당 인터페이스를 구현 string toJson()하는 추상 클래스를 AbstractJsonElement사용하면됩니다.

그런 다음 JSONProperty인터페이스를 구현 하는 클래스 와 추상 클래스를 확장하는 JSONValue(모든 토큰), JSONArray([...]) 및 JSONObject({...}) 만 있으면됩니다.

JSONObject목록이 JSONProperty의이
JSONArray목록이 있습니다AbstractJsonElement 들 '

각각의 추가 함수는 해당 유형의 vararg 목록을 가져 와서 this

이제 당신이 뭔가를 좋아하지 않는다면 그냥 조정할 수 있습니다

인터페이스와 추상 클래스의 JSONArray장점 은 속성을 받아 들일 수 없지만 JSONProperty객체 나 배열을 받아 들일 수 있다는 것입니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.