Làm thế nào để xây dựng thành thạo JSON trong Java?


106

Tôi đang nghĩ về một cái gì đó như:

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

Thư viện Java JSON nào tốt nhất cho kiểu xây dựng thông thạo này?

Cập nhật : Tôi đã gói GSON và nhận được kết quả gần như mong muốn ... chỉ với một lần chạm .


1
Tôi không nghĩ rằng tôi đã thấy bất kỳ thư viện JSON nào theo phong cách đó. Có lẽ bạn có thể mở rộng một thư viện hiện có để làm những gì bạn muốn?
aroth

1
@aroth - Tôi đang viết một bản tóm tắt về com.google.gson khi chúng ta nói chuyện.
ripper234

1
Gần như đã sẵn sàng - stackoverflow.com/questions/8876271/…
ripper234

1
Xây dựng "tổ" Bản đồ và Danh sách thích hợp và tuần tự hóa nó. Tránh phát biểu "polyme chuỗi dài".
Hot Licks

Câu trả lời:


140

Tôi đang sử dụng org.json thư viện và thấy nó rất hay và thân thiện.

Thí dụ:

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

ĐẦU RA:

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

15
Điều này không được trôi chảy nhiều.
Vlad

Trang web bạn đã cung cấp không hoạt động nữa. Bạn có phiền cập nhật nó không?
Saša Zejnilović

13
@Vlad - đây chính xác là những gì mà các nhà xây dựng thông thạo gợi ý cho tôi. Bạn có thể cung cấp một ví dụ về cách thiết lập mà bạn cho là tốt hơn không?
scubbo

3
Đây vẫn là tùy chọn sạch hơn. Thật nực cười rằng Java devs vẫn phải dừng lại để tìm lựa chọn tốt nhất cho JSON phân tích cú pháp / xây dựng trong năm 2020.
mtyson

112

Xem đặc tả Java EE 7 Json . Đây là cách đúng đắn:

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

8
Điều này sẽ được đánh dấu là câu trả lời đúng vào năm 2015 vì đây là một phần của javax.jsonJava 7 trở lên.
Sridhar Sarnobat

42
Nó là Java EE API, không phải Java SE.
igorp1024,

Bất kỳ ý tưởng nào về cách tạo một đối tượng JsonString từ một đối tượng String trong API javax.json?
Raymond


12
Maven phụ thuộc cho duy nhất javax.jsongói là một này
Jean Valjean

12

Gần đây tôi đã tạo một thư viện để tạo các đối tượng Gson một cách trôi chảy:

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

Nó hoạt động như thế này:

  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();

Và thông qua sự kỳ diệu của generics, nó tạo ra lỗi biên dịch nếu bạn cố gắng thêm một phần tử vào một mảng có khóa thuộc tính hoặc một phần tử vào một đối tượng không có tên thuộc tính:

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.

Cuối cùng là hỗ trợ ánh xạ trong API cho phép bạn ánh xạ các đối tượng miền của mình sang JSON. Mục tiêu là khi Java8 được phát hành, bạn sẽ có thể làm những việc như sau:

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

8

Nếu bạn đang sử dụng Jackson làm rất nhiều JsonNode việc xây dựng mã, bạn có thể thấy thú vị với bộ tiện ích sau đây. Lợi ích của việc sử dụng chúng là chúng hỗ trợ phong cách chuỗi tự nhiên hơn, thể hiện rõ hơn cấu trúc của JSON đang được xây dựng.

Đây là một ví dụ sử dụng:

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

...

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

Tương đương với JSON sau:

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

Đây là các lớp:

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

  }

}

Lưu ý rằng việc triển khai sử dụng Lombok , nhưng bạn có thể dễ dàng gỡ bỏ nó để điền vào bản soạn thảo Java.


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

Nếu bạn cho rằng giải pháp trên là thanh lịch, thì hãy dùng thử JsonBuilder lib của tôi . Nó được tạo ra để cho phép một cách xây dựng cấu trúc json cho nhiều loại thư viện Json. Các triển khai hiện tại bao gồm Gson, Jackson và MongoDB. Ví dụ. Jackson chỉ trao đổi:

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

Tôi sẽ vui vẻ thêm những người khác theo yêu cầu, nó cũng khá dễ dàng để tự mình thực hiện.


rất tiếc không có ở trung tâm maven vào lúc này, hãy xem github.com/HknL/JsonBuilder/issues/8
dschulten

1

Có vẻ như bạn có thể muốn xem json-lib:

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

Douglas Crockford là người đã phát minh ra JSON; thư viện Java của anh ấy ở đây:

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

Có vẻ như những người ở json-lib đã chọn nơi Crockford rời đi. Cả hai đều hỗ trợ đầy đủ JSON, cả hai đều sử dụng (tương thích, theo như tôi có thể nói) các cấu trúc JSONObject, JSONArray và JSONFunction.

'Hy vọng điều đó sẽ giúp ..


Nó có hỗ trợ cú pháp thông thạo không?
ripper234,


0

việc viết của riêng bạn dễ dàng hơn nhiều so với bạn nghĩ, chỉ cần sử dụng một giao diện JsonElementInterfacevới một phương thức string toJson()và một lớp trừu tượng AbstractJsonElementtriển khai giao diện đó,

thì tất cả những gì bạn phải làm là có một lớp để JSONPropertytriển khai giao diện và JSONValue(bất kỳ mã thông báo nào), JSONArray([...]) và JSONObject({...}) mở rộng lớp trừu tượng

JSONObjectcó một danh sách của JSONProperty's
JSONArraycó một danh sách của AbstractJsonElement' s

chức năng thêm của bạn trong mỗi chức năng sẽ lấy một danh sách vararg của loại đó và trả về this

bây giờ nếu bạn không thích một cái gì đó, bạn có thể chỉnh sửa nó

lợi ích của lớp inteface và lớp trừu tượng là JSONArraykhông thể chấp nhận các thuộc tính, nhưng JSONPropertycó thể chấp nhận các đối tượng hoặc mảng

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.