Kate
Kate

Reputation: 65

How to read lots of JSON-s from one file

I don't have idea how to read file with lots of JSON-s in Android. I don't even know how many elements are in JSON. This is a part of JSON:

{
  "distance" : 0.0,
  "lat" : 52.297819,
  "lon" : 20.937653,
  "realTime" : 1553448972482,
  "speed" : "NaN",
  "time" : 0.0
}{
  "pulse" : 77,
  "rr" : [ 788 ],
  "time" : 1553448976957
}{
  "distance" : 0.0,
  "lat" : 52.297819,
  "lon" : 20.937653,
  "realTime" : 1553448977481,
  "speed" : "NaN",
  "time" : 0.0
}

I created two model DTO classes:

 public class GpsDTO{
    double lat;
    double lon;
    double speed;
    double distance;
    double time;
    long realTime;
}
 public class HeartDTO{
    long time;
    int pulse;
    int[] rr;
}

and I tried use library GSON but it does not work.

Gson gson = new GsonBuilder().setLenient().create();
try {
    GpsDTO gpsDTO = gson.fromJson(new FileReader(path),GpsDTO.class);
} catch (Exception  e) {
    e.printStackTrace();
}

Upvotes: 1

Views: 103

Answers (1)

Michał Ziober
Michał Ziober

Reputation: 38655

Presented JSON payload is not valid. Gson does not read invalid JSON payloads by default. We need to implement custom deserialiser for it. JSON structure in this case is list of JSON object-es. We can use JsonReader and stream API. The fastest way is to read it once but much easier it to read it twice:

  • Read first time to find order of classes and adapters
  • Read second time to deserialise i - JSON objects using given i - adapter

To match adapter below implementation uses all properties in JSON object (findAdapters method). In case it is not the best algorithm in your case, implement other which fits requirements:

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

Example usage:

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

For your JSON payload prints:

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}

Upvotes: 1

Related Questions