[英]Java Gson parse Json object to array
I'm trying to parse the below Json using the Gson lib in Java.我正在尝试使用 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). 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). Does anyone know if I can change this behaviour of the Gson lib?有谁知道我是否可以更改 Gson 库的这种行为?
{
"Outer": {
"0": {
"Attr1": 12345,
"Attr2": 67890
},
"1": {
"Attr1": 54321,
"Attr2": 09876
}
}
}
The below code demonstrates how Gson parses the array as a JsonObject.下面的代码演示了 Gson 如何将数组解析为 JsonObject。 To be clear, I realise I've referenced outer
as a JsonObject
but I was just doing this to demonstrate the code.需要明确的是,我意识到我已经将outer
引用为JsonObject
,但我这样做只是为了演示代码。 If I try and reference outer
as an JsonArray
, the code fails.如果我尝试将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());
Result:结果:
{"0":{"Attr1":12345,"Attr2":67890},"1":{"Attr1":54321,"Attr2":"09876"}}
false
//edit I'm using this current simple Json as an example, however my application of this code will be to parse Json that's of varying and unknown shape. //编辑我使用这个当前简单的 Json 作为示例,但是我对这段代码的应用将解析 Json,它具有不同的和未知的形状。 I therefore need Gson to automatically parse this to an array so that the isJsonArray
returns true
.因此,我需要 Gson 自动将其解析为数组,以便isJsonArray
返回true
。
TL;DR: See "Using Deserializer" section at the bottom for parsing straight to array. TL;DR:请参阅底部的“使用反序列化器”部分以直接解析为数组。
That JSON does not contain any arrays. JSON 不包含任何 arrays。 An array would use the [...]
JSON syntax.数组将使用[...]
JSON 语法。
Normally, a JSON object would map to a POJO, with the name
in the name/value pairs mapping to a field of the POJO.通常,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. 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.
The JSON object with numeric values as names can be mapped to a Map<Integer, ?>
, eg to parse that JSON to POJOs, do it like this: 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 + "]";
}
}
Test测试
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 Output
Root[outer={0=Outer[attr1=12345, attr2=67890], 1=Outer[attr1=54321, attr2=9876]}]
You can then add a helper method to the Root
class to get that as an array:然后,您可以将辅助方法添加到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;
}
Test测试
System.out.println(Arrays.toString(root.getOuterAsArray()));
Output Output
[Outer[attr1=12345, attr2=67890], Outer[attr1=54321, attr2=9876]]
However, it would likely be more useful if the conversion to array is done while parsing, so you need to write a JsonDeserializer
and tell Gson about it using @JsonAdapter
:但是,如果在解析时完成转换为数组可能会更有用,因此您需要编写一个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;
}
}
Same Outer
class and test code as above.与上面相同的Outer
class 和测试代码。
Output Output
Root[outer=[Outer[attr1=12345, attr2=67890], Outer[attr1=54321, attr2=9876]]]
I'll asume your JsonObject
is a POJO class such like:我假设您的JsonObject
是 POJO class ,例如:
public Inner[] outer;
If you want an array of objects you can change your code to:如果您想要一个对象数组,您可以将代码更改为:
Inner[] jo = gson.fromJson(json, Inner[].class);
Please refer below code 1.To get an array of Objects (outerArray) 2.You can extract a JsonArray
(outerJsonArray) containing values of inner objects in Outer
(in case keys aren't significant for further use)请参考下面的代码 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());
}
You can use the JsonNode class's method findParent findValue and findPath which reduce your code as compare to another parsing library.您可以使用 JsonNode 类的方法 findParent findValue 和 findPath 与另一个解析库相比,它们会减少您的代码。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.