簡體   English   中英

Java Gson 解析 Json ZA8CFDE6331BD59EB2AC96F8911C4B66Z 到數組

[英]Java Gson parse Json object to array

我正在嘗試使用 Java 中的 Gson 庫來解析以下 Json。 When using other languages, such as C#, this JSON is parsed into an array, however it seems Gson converts this into a set of java attributes (which to be honest, makes more sense to me). 有誰知道我是否可以更改 Gson 庫的這種行為?

{
  "Outer": {
    "0": {
      "Attr1": 12345,
      "Attr2": 67890
    },
    "1": {
      "Attr1": 54321,
      "Attr2": 09876
    }
  }
}

下面的代碼演示了 Gson 如何將數組解析為 JsonObject。 需要明確的是,我意識到我已經將outer引用為JsonObject ,但我這樣做只是為了演示代碼。 如果我嘗試將outer引用為JsonArray ,則代碼將失敗。

String json = "{\"Outer\": { \"0\": { \"Attr1\": 12345, \"Attr2\": 67890 }, \"1\": { \"Attr1\": 54321, \"Attr2\": 09876 }}}";
Gson gson = new GsonBuilder()
            .disableHtmlEscaping()
            .setLenient()
            .serializeNulls()
            .create();

JsonObject jo = gson.fromJson(json, JsonObject.class);
JsonObject outer = jo.getAsJsonObject("Outer");

System.out.println(outer);
System.out.println(outer.isJsonArray());

結果:

{"0":{"Attr1":12345,"Attr2":67890},"1":{"Attr1":54321,"Attr2":"09876"}}
false

//編輯我使用這個當前簡單的 Json 作為示例,但是我對這段代碼的應用將解析 Json,它具有不同的和未知的形狀。 因此,我需要 Gson 自動將其解析為數組,以便isJsonArray返回true

TL;DR:請參閱底部的“使用反序列化器”部分以直接解析為數組。


JSON 不包含任何 arrays。 數組將使用[...] JSON 語法。

通常,JSON object 將 map 映射到 POJO, name /值對中的名稱映射到 POJO 的字段。

However, a JSON object can also be mapped to a Map , which is especially useful when the names are dynamic, since POJO fields are static.

使用 Map

JSON object 可以將數值作為名稱映射到Map<Integer, ?> ,例如將 JSON 解析為 POJO:

class Root {
    @SerializedName("Outer")
    public Map<Integer, Outer> outer;
    @Override
    public String toString() {
        return "Root[outer=" + this.outer + "]";
    }
}
class Outer {
    @SerializedName("Attr1")
    public int attr1;
    @SerializedName("Attr2")
    public int attr2;
    @Override
    public String toString() {
        return "Outer[attr1=" + this.attr1 + ", attr2=" + this.attr2 + "]";
    }
}

測試

Gson gson = new GsonBuilder().create();
Root root;
try (BufferedReader in = Files.newBufferedReader(Paths.get("test.json"))) {
    root = gson.fromJson(in, Root.class);
}
System.out.println(root);

Output

Root[outer={0=Outer[attr1=12345, attr2=67890], 1=Outer[attr1=54321, attr2=9876]}]

獲取為數組

然后,您可以將輔助方法添加到Root class 以將其作為數組獲取:

public Outer[] getOuterAsArray() {
    if (this.outer == null)
        return null;
    if (this.outer.isEmpty())
        return new Outer[0];
    int maxKey = this.outer.keySet().stream().mapToInt(Integer::intValue).max().getAsInt();
    Outer[] arr = new Outer[maxKey + 1];
    this.outer.forEach((k, v) -> arr[k] = v);
    return arr;
}

測試

System.out.println(Arrays.toString(root.getOuterAsArray()));

Output

[Outer[attr1=12345, attr2=67890], Outer[attr1=54321, attr2=9876]]

使用解串器

但是,如果在解析時完成轉換為數組可能會更有用,因此您需要編寫一個JsonDeserializer並使用@JsonAdapter

class Root {
    @SerializedName("Outer")
    @JsonAdapter(OuterArrayDeserializer.class)
    public Outer[] outer;

    @Override
    public String toString() {
        return "Root[outer=" + Arrays.toString(this.outer) + "]";
    }
}
class OuterArrayDeserializer implements JsonDeserializer<Outer[]> {
    @Override
    public Outer[] deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
        // Parse JSON array normally
        if (json.isJsonArray())
            return context.deserialize(json, Outer[].class);

        // Parse JSON object using names as array indexes
        JsonObject obj = json.getAsJsonObject();
        if (obj.size() == 0)
            return new Outer[0];
        int maxKey = obj.keySet().stream().mapToInt(Integer::parseInt).max().getAsInt();
        Outer[] arr = new Outer[maxKey + 1];
        for (Entry<String, JsonElement> e : obj.entrySet())
            arr[Integer.parseInt(e.getKey())] = context.deserialize(e.getValue(), Outer.class);
        return arr;
    }
}

與上面相同的Outer class 和測試代碼。

Output

Root[outer=[Outer[attr1=12345, attr2=67890], Outer[attr1=54321, attr2=9876]]]

我假設您的JsonObject是 POJO class ,例如:

public Inner[] outer;

如果您想要一個對象數組,您可以將代碼更改為:

Inner[] jo = gson.fromJson(json, Inner[].class);

請參考下面的代碼 1.獲取對象數組(outerArray) 2.您可以提取包含Outer中內部對象值的JsonArray (outerJsonArray)(以防鍵對進一步使用不重要)

String json = "{\"Outer\": { \"0\": { \"Attr1\": 12345, \"Attr2\": 67890 }, \"1\": { \"Attr1\": 54321, \"Attr2\": 09876 }}}";
Gson gson = new GsonBuilder().disableHtmlEscaping().setLenient().serializeNulls().create();
JsonObject jo = gson.fromJson(json, JsonObject.class);
JsonObject outer = jo.getAsJsonObject("Outer");

Object[] outerArray = outer.entrySet().toArray();
// outerArray: [0={"Attr1":12345,"Attr2":67890}, 1={"Attr1":54321,"Attr2":"09876"}]

JsonArray outerJsonArray = new JsonArray();
outer.keySet().stream().forEach(key -> {
outerJsonArray.add(outer.get(key));
});
//jsonArray=[{"Attr1":12345,"Attr2":67890},{"Attr1":54321,"Attr2":"09876"}]

System.out.println(outer);
System.out.println(outerJsonArray.isJsonArray() + " " + outerJsonArray);
Jackson – Marshall String to JsonNode will be useful in your case.with following pom:- 


    //POM FILE


        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.9.8</version>
        </dependency>

//JAVA CODE
    //read json file data to String


     byte[] jsonData = Files.readAllBytes(Paths.get("employee.txt"));

        //create ObjectMapper instance
        ObjectMapper objectMapper = new ObjectMapper();

        //read JSON like DOM Parser
        JsonNode rootNode = objectMapper.readTree(jsonData);
        JsonNode idNode = rootNode.path("id");
        System.out.println("id = "+idNode.asInt());

        JsonNode phoneNosNode = rootNode.path("phoneNumbers");
        Iterator<JsonNode> elements = phoneNosNode.elements();
        while(elements.hasNext()){
            JsonNode phone = elements.next();
            System.out.println("Phone No = "+phone.asLong());
        }

您可以使用 JsonNode 類的方法 findParent findValue 和 findPath 與另一個解析庫相比,它們會減少您的代碼。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM