How do I parse Json data with Gson when not everything is labelled
How do I parse Json data with Gson when not everything is labelled
I have happily been using Google Gson to parse extract some JSON metadata of the form
Gson
"lowlevel":
"average_loudness": 0.570070445538
,
"rhythm":
"beats_count": 502,
"bpm": 128.347702026
,
"tonal":
"chords_changes_rate": 0.0534749031067
"tuning_diatonic_strength": 0.431238204241,
"tuning_equal_tempered_deviation": 0.164615109563,
"tuning_frequency": 434.193115234,
"tuning_nontempered_energy_ratio": 0.847496032715
Using this
public class AcousticBrainzLowlevelWrapper
private AcousticBrainzLowLevelRhythm rhythm;
private AcousticBrainzLowLevelTonal tonal;
public AcousticBrainzLowLevelRhythm getRhythm()
return rhythm;
public void setRhythm(AcousticBrainzLowLevelRhythm rhythm)
this.rhythm = rhythm;
public AcousticBrainzLowLevelTonal getTonal()
return tonal;
public void setTonal(AcousticBrainzLowLevelTonal tonal)
this.tonal = tonal;
and
AcousticBrainzLowlevelWrapper low = gson.fromJson(result, AcousticBrainzLowlevelWrapper.class) ;
(Full JSON can be seen here)
but now the API has been extended to allow multiple lookups such as this url
which now returns
{
"96685213-a25c-4678-9a13-abd9ec81cf35": {
"0":
"lowlevel":
"average_loudness": 0.570070445538
,
"rhythm":
"beats_count": 502,
"bpm": 128.347702026
,
"tonal":
"chords_changes_rate": 0.0534749031067
"tuning_diatonic_strength": 0.431238204241,
"tuning_equal_tempered_deviation": 0.164615109563,
"tuning_frequency": 434.193115234,
"tuning_nontempered_energy_ratio": 0.847496032715
.....
"78787888-a25c-4678-9a13-abd9ec81cf35": {
"0": {
"lowlevel": {
......
..
The difference being that the json doesn't define what "96685213-a25c-4678-9a13-abd9ec81cf35" and "78787888-a25c-4678-9a13-abd9ec81cf35" are, or what "0" is.
So I know what they represent (MusicBrainzRecording and offset) but I cannot create a class like AcousticBrainzLowlevelWrapper to represent this, so how do I parse this new api.
AcousticBrainzLowlevelWrapper
Update
I tried creating
public class AcousticBrainzLowLevelList
private Map<String, AcousticBrainzLowlevelWrapper> data = new HashMap<>();
public Map<String, AcousticBrainzLowlevelWrapper> getData()
return data;
public void setData(Map<String, AcousticBrainzLowlevelWrapper> data)
this.data = data;
and then calling
AcousticBrainzLowLevelList lowMap = gson.fromJson(result, AcousticBrainzLowLevelList.class) ;
but nothing get added to the map. Unsuprisingly because data I dont' see how can i give a name since there is no consistent name at the top level.
data
Map
Right, so i guess I need to create a wrapper class for AcousticBrainzLowlevelWrapper that contains map of them, not clear on what it should look like.
– Paul Taylor
Aug 21 at 12:55
I think you should have a key
String map of your current AcousticBrainzLowlevelWrapper like this Map<String, AcousticBrainzLowlevelWrapper>– Mickaël B
Aug 21 at 12:59
String
AcousticBrainzLowlevelWrapper
Map<String, AcousticBrainzLowlevelWrapper>
Isnt it more complex than that because at top level there each contains "0" (Xml is so much easier to understand !)
– Paul Taylor
Aug 21 at 13:01
2 Answers
2
It seems to me that your input JSON could be parsed to produce a Java class of type Map<String,Map<Integer,AcousticBrainzLowlevelWrapper>> :
Map<String,Map<Integer,AcousticBrainzLowlevelWrapper>>
Type type = new TypeToken<Map<String,Map<Integer,AcousticBrainzLowlevelWrapper>>>().getType();
Map<String,Map<Integer,AcousticBrainzLowlevelWrapper>> result = gson.fromJson(json, type);
HI, I dont seem able to access com.google.gson.reflect.TypeToken says has protected access ?
– Paul Taylor
Aug 21 at 13:35
You beat me to it, I just finished testing the same solution :)
– Bentaye
Aug 21 at 13:37
@PaulTaylor he forgot
, try like this: Type type = new TypeToken<Map<String,Map<Integer,AcousticBrainzLowlevelWrapper>>>().getType();– Bentaye
Aug 21 at 13:41
Type type = new TypeToken<Map<String,Map<Integer,AcousticBrainzLowlevelWrapper>>>().getType();
@Bentaye you're right. Just corrected.
– Maurice Perry
Aug 21 at 13:42
Brilliant, that works. My only question is does the outer map it use a sortedmap, if not can it be so is same order as the json
– Paul Taylor
Aug 21 at 13:59
As I wrote it, I might as well post it:
Similar to Maurice's answer
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import java.lang.reflect.Type;
import java.util.Map;
public class Main
private final static String jsonSingle =
" "attribute1": "value1", "attribute2": "value2" ";
private final static String jsonMultiple =
"n" +
" "96685213-a25c-4678-9a13-abd9ec81cf35": n" +
" "0": "attribute1": "value1", "attribute2": "value2" n" +
" ,n" +
" "78787888-a25c-4678-9a13-abd9ec81cf35": n" +
" "0": "attribute1": "value3", "attribute2": "value4" n" +
"";
public static void main(String args)
MyBean bean = new Gson().fromJson(jsonSingle, MyBean.class);
System.out.println(bean);
Type type = new TypeToken<Map<String, Map<String, MyBean>>>().getType();
Map<String, String> myMap = new Gson().fromJson(jsonMultiple, type);
System.out.println(myMap);
MyBean class:
class MyBean
String attribute1;
String attribute2;
public String getAttribute1()
return attribute1;
public void setAttribute1(String attribute1)
this.attribute1 = attribute1;
public String getAttribute2()
return attribute2;
public void setAttribute2(String attribute2)
this.attribute2 = attribute2;
@Override
public String toString()
return "MyBean: <attribute1: " + attribute1 + "
Outputs:
MyBean: <attribute1: value1 | attribute2: value2>
and
96685213-a25c-4678-9a13-abd9ec81cf35=0=MyBean: <attribute1: value1 , 78787888-a25c-4678-9a13-abd9ec81cf35=0=MyBean: <attribute1: value3
Thanks for taking the time to do this, but the other answer is more closely aligned to my data.
– Paul Taylor
Aug 21 at 14:04
By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.
I think this is a
Map.– Mickaël B
Aug 21 at 12:52