How do parse JSON Array with other data types with Gson using a class?

43 Views Asked by At

I am trying to read three things from a JSON file like this (I left out the fields I did not need):

{
 "results": [
    {
      "c": 75.0875,
      "h": 75.15,
      "l": 73.7975,
      "n": 1,
      "o": 74.06,
      "t": 1577941200000,
      "v": 135647456,
      "vw": 74.6099
    },
    {
      "c": 74.3575,
      "h": 75.145,
      "l": 74.125,
      "n": 1,
      "o": 74.2875,
      "t": 1578027600000,
      "v": 146535512,
      "vw": 74.7026
    }
  ],
  "status": "OK",
  "ticker": "AAPL"
}

And to do that, I use this code:

Relevant lines from main class:

Transcript transcript = new Transcript();
Gson gson = new Gson();
// HTTP Requests here
transcript = gson.fromJson(getResponse.body(), Transcript.class);
// "status" verification
System.out.println(transcript.getResults());

Transcript class:

public class Transcript {
    public Type results = new TypeToken<ArrayList<DataObject>>(){}.getType();
    public String ticker = "AAPL";
    public String status;

    // Getters and setters too
}

DataObject class:

public class DataObject {
    public String tag;
    public double value;

    public DataObject(String tag, double value){
        this.tag = tag;
        this.value = value;
    }

    public String toString() {
        return "tag = " + tag + ", value = " + value;
    }
}

There were a few errors when I tried different fixes, mostly regarding to Object type, but the current error is: Caused by: com.google.gson.JsonIOException: Interfaces can't be instantiated! Register an InstanceCreator or a TypeAdapter for this type. Interface name: java.lang.reflect.Type

I tried a few variations of this line:

public Type results = new TypeToken<ArrayList<DataObject>>(){}.getType();

I tried DataObject arrays, nested ArrayList, etc. but honestly I'm not completely confident in what I'm doing because it's my first time reading json files, so I'm just taking shots.

I tried following this previous question: How to Parse JSON Array with Gson, but it does not have other fields than the array, nor does it use a separate class. This may be relevant, but changing [public] -> [private] in the DataObject and Transcript classes throws this error: com.google.gson.JsonIOException: Failed making field 'piemanray314.testingjavafx.testingjavafx.Transcript#results' accessible; either increase its visibility or write a custom TypeAdapter for its declaring type.

1

There are 1 best solutions below

0
Herbert Marshall On

You're getting the error:

Caused by: com.google.gson.JsonIOException: Interfaces can't be instantiated! Register an InstanceCreator or a TypeAdapter for this type

because GSON is trying to create the Transcript class, but it cannot find a way to create the field 'results' because it is only an interface which cannot be created without an implementation.

You'll need to create a class that mirrors the results objects and it should work

@Test
void parseJson() {
    String json = """
    {
     "results": [
        {
          "c": 75.0875,
          "h": 75.15,
          "l": 73.7975,
          "n": 1,
          "o": 74.06,
          "t": 1577941200000,
          "v": 135647456,
          "vw": 74.6099
        },
        {
          "c": 74.3575,
          "h": 75.145,
          "l": 74.125,
          "n": 1,
          "o": 74.2875,
          "t": 1578027600000,
          "v": 146535512,
          "vw": 74.7026
        }
      ],
      "status": "OK",
      "ticker": "AAPL"
    }
""";

    Transcript transcript = new Transcript();
    Gson gson = new Gson();

    transcript = gson.fromJson( json, Transcript.class );

    System.out.println(transcript.getResults());
}

public class Transcript {
    private Set<Result> results;
    private String ticker = "AAPL";
    private String status;

    public Set<Result> getResults() {
        return results;
    }

}

public class Result {
    private double c;
    private double h;
    private double l;
    private int n;
    private double o;
    private long t;
    private int v;
    private double vw;

    @Override
    public String toString() {
        return "Result{" +
            "c=" + c +
            ", h=" + h +
            ", l=" + l +
            ", n=" + n +
            ", o=" + o +
            ", t=" + t +
            ", v=" + v +
            ", vw=" + vw +
            '}';
    }
}