问题
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, List.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
回答1:
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.
回答2:
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.
回答3:
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.
回答4:
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);
来源:https://stackoverflow.com/questions/5911558/java-deserializing-json-structure-to-mapstring-object