2

i'm new to gson and i wonder how convert json data to LinkedHashMap<String, List<String>>

my json data is show like below:

{ "data": 
    {
        "data1": ["asdf", "qwer"],
        "data2": ["xczv", "aweqrfds123", "sfdgq234"],
        "data3": ["dsafasd", "xcvr123", "sdfa324123"] 
    }
}

field names of json data of data are dynamic, so i want to convert json data of data to LinkedHashMap<String, List<String>>

how can i do that ?

Braj
  • 46,415
  • 5
  • 60
  • 76
crazy_rudy
  • 533
  • 2
  • 4
  • 19

2 Answers2

2

You can use TypeToken to convert it into expected type with Gson#fromJson(Reader,Type)

As per JSON string it is LinkedHashMap<String,LinkedHashMap<String,ArrayList<String>>>

Sample code:

BufferedReader reader = new BufferedReader(new FileReader(new File("json.txt")));
Type type = new TypeToken<LinkedHashMap<String,LinkedHashMap<String,ArrayList<String>>>>() {}.getType();

LinkedHashMap<String,LinkedHashMap<String,ArrayList<String>>> data = new Gson().fromJson(reader, type);
LinkedHashMap<String,ArrayList<String>> innerMap = data.get("data");

System.out.println(new GsonBuilder().setPrettyPrinting().create().toJson(innerMap));
Braj
  • 46,415
  • 5
  • 60
  • 76
  • It's a cool, but tricky approach and I've even made it working after fixing few syntax errors, but it's not universal, e.g. if you add 'data4' to json with a value which is not a string list, it's not going to work, so I would stick to a classical approach. – Oleg Gryb Jul 30 '14 at 18:39
  • I can't create a POJO because as per OP the JSON string keys are dynamic in that case Map works perfectly. You can change it to Object as value in Map. – Braj Jul 30 '14 at 18:41
  • It "works perfectly" until I add something like "data4":"foo" to the json at which point you'll get IllegalStateException. – Oleg Gryb Jul 30 '14 at 18:44
  • As I said you use `Map` then use the `instanceof` operator to check for value type. – Braj Jul 30 '14 at 18:45
  • It makes everything even more complicated and tricky. Why doing all that if you can just generate a class and avoid all that complexity? – Oleg Gryb Jul 30 '14 at 18:47
  • can I generated class at runtime? where I don't know what are the variable names. How will I change the class if key is changed to `k1`, `k2` instead of `data1`, `data2` – Braj Jul 30 '14 at 18:48
  • you can through reflection, but why? – Oleg Gryb Jul 30 '14 at 18:49
  • the JSON string is not static. the kay can be anything. In that case you can't define class. Reflection is not a good way. – Braj Jul 30 '14 at 18:50
  • Well, your tricky approach is not much better and it already uses reflection. Besides, the whole dynamic json processing was not in the scope of the question. My point was that if I need to add a key with a different value type, I would rather re-generate the class than do instance type evaluation in the code. After few changes to the initial JSON format your code will become unreadable, so once again my advice would be to use a classical approach. – Oleg Gryb Jul 30 '14 at 18:55
  • No discussion. [Read here](http://stackoverflow.com/questions/6796662/using-gson-to-parse-a-json-with-dynamic-key-and-value-in-android) – Braj Jul 30 '14 at 18:58
0

This is not how it works in Gson world - you can't convert JSON to any Java class you want, unless you want to do all of that manually. The common approach works as described below:

  1. Create a Java class, which matches your JSON format, e.g. you can use a Java class generator described here: http://jsongen.byingtondesign.com/
  2. Use GsonBuilder to read your Json from a file and to import it to the generated class

I've used that approach and the Java file that has been generated (after I've fixed a minor syntax error in your initial JSON) looks like this:

package com.json;

import java.util.List;

public class Data{
    private List data1;
    private List data2;
    private List data3;

    public List getData1(){
        return this.data1;
    }
    public void setData1(List data1){
        this.data1 = data1;
    }
    public List getData2(){
        return this.data2;
    }
    public void setData2(List data2){
        this.data2 = data2;
    }
    public List getData3(){
        return this.data3;
    }
    public void setData3(List data3){
        this.data3 = data3;
    }
}

To start working with the newly created class you can use the template below:

        is = new InputStreamReader(new FileInputStream(new File('<path-to-json>')), "UTF-8")/;
        Gson gson = new GsonBuilder().create();
        Data d = gson.fromJson(is, Data.class);
        // Start using your d instance here
Oleg Gryb
  • 5,122
  • 1
  • 28
  • 40