Представлено JSON
Полезная нагрузка недействительна.Gson
не считывает недопустимые JSON
полезные данные по умолчанию.Для этого нам нужно реализовать собственный десериализатор.Структура JSON
в этом случае представляет собой список JSON object
-es.Мы можем использовать JsonReader
и поток API
.Самый быстрый способ - прочитать его один раз, но гораздо проще прочитать его дважды:
- Прочитать в первый раз, чтобы найти порядок классов и адаптеров
- Прочитать во второй раз для десериализации
i - JSON objects
используя заданный i - adapter
Для соответствия адаптеру, приведенному ниже, реализация использует все свойства объекта JSON
(метод findAdapters
).Если в вашем случае это не лучший алгоритм, реализуйте другой, который соответствует требованиям:
class MultiJsonReader {
// constant list of properties for each class
private final List<String> HEART_PROPS = Arrays.asList("pulse", "rr", "time");
private final List<String> GPS_PROPS = Arrays.asList("lat", "lon", "distance", "speed", "realTime", "time");
private final Gson gson;
public MultiJsonReader(Gson gson) {
this.gson = gson;
}
public List<Object> readAll(File jsonFile) throws IOException {
List<TypeAdapter<?>> adapters;
// read first time for finding types and adapters
try (JsonReader jsonReader = gson.newJsonReader(new FileReader(jsonFile))) {
jsonReader.setLenient(true);
adapters = findAdapters(gson, jsonReader);
}
List<Object> objects = new ArrayList<>();
// read second time for deserialising
try (JsonReader jsonReader = gson.newJsonReader(new FileReader(jsonFile))) {
jsonReader.setLenient(true);
for (TypeAdapter<?> adapter : adapters) {
objects.add(adapter.read(jsonReader));
}
}
return objects;
}
private List<TypeAdapter<?>> findAdapters(Gson gson, JsonReader jsonReader) throws IOException {
List<TypeAdapter<?>> adapters = new ArrayList<>();
while (jsonReader.peek() != JsonToken.END_DOCUMENT) {
List<String> names = new ArrayList<>();
jsonReader.beginObject();
while (jsonReader.peek() != JsonToken.END_OBJECT) {
names.add(jsonReader.nextName());
jsonReader.skipValue();
}
jsonReader.endObject();
Class<?> clazz = getClassForProperties(names);
adapters.add(gson.getAdapter(clazz));
}
return adapters;
}
private Class<?> getClassForProperties(List<String> properties) {
if (HEART_PROPS.containsAll(properties)) {
return HeartDTO.class;
}
if (GPS_PROPS.containsAll(properties)) {
return GpsDTO.class;
}
throw new IllegalArgumentException("Properties are not known " + properties);
}
}
Пример использования:
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.TypeAdapter;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonToken;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class GsonApp {
public static void main(String[] args) throws Exception {
File jsonFile = new File("./resource/test.json").getAbsoluteFile();
Gson gson = new GsonBuilder().create();
MultiJsonReader reader = new MultiJsonReader(gson);
List<Object> objects = reader.readAll(jsonFile);
objects.forEach(System.out::println);
}
}
Для ваших JSON
распечаток полезной нагрузки:
GpsDTO{lat=52.297819, lon=20.937653, speed=NaN, distance=0.0, time=0.0, realTime=1553448972482}
HeartDTO{time=1553448976957, pulse=77, rr=[788]}
GpsDTO{lat=52.297819, lon=20.937653, speed=NaN, distance=0.0, time=0.0, realTime=1553448977481}