TL; DR: См. Раздел «Использование десериализатора» в нижней части для разбора прямо в массив.
Что JSON не содержит любые массивы. Массив будет использовать синтаксис [...]
JSON.
Обычно объект JSON сопоставляется с POJO, а name
в парах имя / значение отображается в поле POJO .
Однако объект JSON также можно сопоставить с Map
, что особенно полезно, когда имена являются динамическими c, так как поля POJO имеют статус c.
Использование карты
Объект JSON со значениями числительных c в качестве имен можно сопоставить с 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);
Выход
Root[outer={0=Outer[attr1=12345, attr2=67890], 1=Outer[attr1=54321, attr2=9876]}]
Получить как массив
Затем вы можете добавить вспомогательный метод к классу Root
, чтобы получить его в виде массива:
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()));
Вывод
[Outer[attr1=12345, attr2=67890], Outer[attr1=54321, attr2=9876]]
Использование десериализатора
Однако, вероятно, было бы более полезно, если преобразование в массив выполняется во время синтаксического анализа, поэтому вам нужно написать JsonDeserializer
и скажите Gson об этом, используя @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
и тестовый код, что и выше.
Выход
Root[outer=[Outer[attr1=12345, attr2=67890], Outer[attr1=54321, attr2=9876]]]