Java: Deserializing JSON structure to Map<String, Object>
I've got a JSON string that I want to convert to a Map structure where Object is either a Java version of a basic type (i.e. String, Int, Double), a Map. or a List.
The sample string I'm using for my tests is:
"{\"cases\":[{\"documents\":[{\"files\":[{\"name\":\"a.pdf\"}]}]}]}"
This should read as an array of cases that each have an array of documents, that each have an array of files, that each have a name
I've tried Google's Gson, but
Gson gson = new Gson();
List<Map<String, Object>> results = gson.fromJson(dictString, Lis开发者_如何学JAVAt.class);
gives me:
com.google.gson.JsonParseException: The JsonDeserializer com.google.gson.DefaultTypeAdapters$CollectionTypeAdapter@561777b1 failed to deserialize json object {"cases":[{"documents":[{"files":[{"name":"a.pdf"}]}]}]} given the type interface java.util.List
and I tried Jackson, but
List<Map<String, Object>> results = (List<Map<String, Object>>) new ObjectMapper().readValue(dictString, List.class);
gave me:
org.codehaus.jackson.map.JsonMappingException: Can not deserialize instance of java.util.List out of START_OBJECT token
at [Source: java.io.StringReader@1c5aebd9; line: 1, column: 1]
Do you have any suggestions? Either for how to use either of the above correctly, or for another parser that gives me what I want?
Cheers
Nik
I stumbled in here with the same problem and I found a simple solution. I'm posting a more clear answer just in case it helps someone else:
String jsonString = "{ \"first-name\" : \"John\" }";
//creates, essentially a wrapper for a HashMap containing your JSON dictionary
JSONObject genericMap = new JSONObject(jsonString);
//calls to "put" and "get" are delegated to an internal hashmap
String name = (String) genericMap.get("first-name");
assertEquals("John", name); //passes
genericMap.put("last-name", "Doe"); //add any object to the hashmap
//the put methods can be used fluidly
genericMap.put("weight", 150).put("height", "5'10").put("age", "32");
//finally, you can write it back out to JSON, easily
String newJson = genericMap.toString(4); //pretty-print with 4 spaces per tab
log.debug(newJson);
this prints the following:
{
"age": "32",
"first-name": "John",
"height": "5'10",
"last-name": "Doe",
"weight": 150
}
Add this dependency to your project like this:
<dependency>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
<version>20090211</version>
</dependency>
Or download the JAR directly:
http://repo1.maven.org/maven2/org/json/json/20090211/json-20090211.jar
I already had this class available (it was a transient dependency of something else in our project). So be sure to check if it's already there first. You might get lucky, too.
Given your description, it sounds like your definition doesn't match up. It dounds like it should be something like: List<List<list<String>>>
It's a bit more manual but have a look here:
http://json.org/java/
This will give you a JSONObject that is much easier to use than parsing the string yourself, but you will still have to drill into it and manually build your map. Kind of a half and half solution.
The easiest thing might be just to do it yourself: use something like GSON or tapestry's JSONObject to construct a java representatin of your json, then just iterate through it and build whatever map structure you like.
Using gson library:
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>${gson.version}</version>
</dependency>
First you need to create a type. Let's suppose you need a Map<String,Foo>
then change:
private static final Type INPUT_MAP_TYPE = new TypeToken<Map<String, Foo>>() {}.getType();
Then, have a generic method of the type:
protected <T> T readJson(String fileName, Type type) {
InputStreamReader ir = new InputStreamReader(getClass().getClassLoader().getResourceAsStream(fileName));
return new Gson().fromJson(ir, type);
}
Where Type is in package java.lang.reflect;
Enjoy:
Map<String, Foo> inputParams = readJson("path/to/my.json", INPUT_MAP_TYPE);
精彩评论