How to convert JSON of JSONs to array of JSONs in Java?

88 views Asked by At

I've been running into some issues on a personal project of mine. I fetch the data field from the url: http://ddragon.leagueoflegends.com/cdn/13.15.1/data/en_US/champion.json with the following code:

import DataHandlers.ChampionsJson;

import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.util.concurrent.ExecutionException;


public class ChampionsDataScheduler extends Thread{
    @Override
    public void run(){
        while(true){

            try {
                var client = HttpClient.newHttpClient();

                var request = HttpRequest.newBuilder(
                                URI.create("http://ddragon.leagueoflegends.com/cdn/13.15.1/data/en_US/champion.json"))
                        .header("accept", "application/json")
                        .build();

                var responseFuture = client.sendAsync(request, new JsonBodyHandler<>(ChampionsJson.class));
                var response = responseFuture.get();
                var data = response.body().get().championsData;

                System.out.println(data);
                Thread.sleep(1000);

            } catch (InterruptedException | ExecutionException e) {
                throw new RuntimeException(e);
            }


        }
    }
}

Using this class:

package DataHandlers;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.JsonNode;

import java.util.List;

@JsonIgnoreProperties(ignoreUnknown = true)
public class ChampionsJson {
    public final JsonNode championsData;

    @JsonIgnoreProperties(ignoreUnknown = true)
    public ChampionsJson(@JsonProperty("data") JsonNode championsData) {
        this.championsData = championsData;
    }
}

I'm trying to inject each champion (each value in the received json) to the following object and create an array of it:

package DataHandlers;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;

import java.util.List;
@JsonIgnoreProperties(ignoreUnknown = true)
public class ChampionsData {
    public final String id;
    public final String name;
    public final String blurb;
    public final List image;
    public final String title;

    @JsonIgnoreProperties(ignoreUnknown = true)
    public ChampionsData(@JsonProperty("id") String id,
                @JsonProperty("name") String name,
                @JsonProperty("blurb") String blurb,
                @JsonProperty("image") List image,
                @JsonProperty("title") String title) {
        this.id = id;
        this.name = name;
        this.title = title;
        this.blurb = blurb;
        this.image = image;
    }


}

but I fail to do so because I get the JSON as a string of JSONs, and I haven't figured out a way to parse it correctly. Any idea how to do that? Is there maybe a better way to do so?

If you want to get more context on it, my final goal is to convert the ChampionsData object array to a morphia object array and insert it into Mongo.

1

There are 1 answers

4
Buzz Moschetti On BEST ANSWER

The data at http://ddragon.leagueoflegends.com/cdn/13.15.1/data/en_US/champion.json is a single JSON object with a single key data. data is an object with approx 164 subfields, each of which appears to be the name of a champion. There are no arrays; you must iterate over the data field.

If the goal is to insert this data into MongoDB, then I recommend making each champion a separate document. The subfields carry a lot of identifying information like name,key, and id so let's keep that and let MongoDB client side driver invent the _id.

The OQ code attempts to take image and store it as a list. image from the JSON is not a list; it is an object (a substructure). In the code below, we will copy over the whole image object into the Document to be inserted.

// The OQ code to fetch the JSON is directionally correct.   It results in 
// the JSON string being stored in variable `data` and sort of trapped in
// the thread but the approach is fine.  The details of organizing the
// code to schedule and fetch the data are not relevant to the question.

ObjectMapper mapper = new ObjectMapper(); 

//  OP has JSON string somewhere in the mix of @championsData; not sure
//  how it is wired together but the goal is the same: to parse the
//  JSON into a Java Map object using mapper.  As a proxy, we show
//  readValue() from a file here:
Map<String,Object> content = mapper.readValue(new File(fileName), Map.class);

String host = "mongodb://your_connection_uri";
MongoClient client = MongoClients.create(host);
MongoDatabase db = client.getDatabase("testX");
MongoCollection<Document> coll = db.getCollection("foo", Document.class);

java.util.Map data = (java.util.Map) content.get("data");
      
data.forEach(
             (key, value)
             -> {
                 //  Use this to deep copy all fields for each champion:             
                 //Document dd = new Document((Map)value);                           

                 // .. or this to only pick up select items:                         
                 Document dd = new Document();
                 Map m = (Map)value;
                 for(String k2 : new String[]{"name","blurb","title","image"}) {
                     dd.put(k2, m.get(k2));
                 }
                 coll.insertOne(dd);
             });