I have a class having trivial string typed fields and one map only:
class MyClass {
@SerializedName("handle");
String nickName;
Map randomDetails;
}
My requirement is to create a map of fieldName to fieldValue (Map) but the fieldNames should be the same as @SerializedName rather than Myclass's field name. I realize that for a complex type like MyClass I m开发者_StackOverfloway have to do some low-level deserialization myself. Has anyone come across this?
If you use a library, you shouldn't need to do any low-level work.
I haven't used it (yet) but Jackson looks like it'll do what you need.
It would be especially easy if you're not required to use that @SerializedName
annotation, as Jackson provides a suite of its own annotations which do exactly what you need - (see the @JsonProperty
annotation).
If you use the Jackson Tree Model mode of operation, you should get something like the map-based results you're looking for.
(I think I understand that the question concerns how to use Gson to deserialize a JSON map structure to a Java Map
.)
Gson currently needs a little bit more type information about the Map
than the Java class structure in the original question provides. Instead of declaring that randomDetails
is a plain old Map
, let Gson know that it's a Map<String, String>
. Then, the following example JSON and simple deserialization code runs as expected.
input.json Contents:
{
"handle":"the handle",
"random_details":{"one":1,"too":"B","3":false,"for":5.32}
}
Foo.java:
import java.io.FileReader;
import java.util.Map;
import com.google.gson.FieldNamingPolicy;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.annotations.SerializedName;
public class Foo
{
public static void main(String[] args) throws Exception
{
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES);
Gson gson = gsonBuilder.create();
MyClass myObject = gson.fromJson(new FileReader("input.json"), MyClass.class);
System.out.println(gson.toJson(myObject));
}
}
class MyClass
{
@SerializedName("handle")
String nickName;
Map<String, String> randomDetails;
}
Note that this converts all values in the Map
into Strings
. If you wanted something more generic, like a Map<String, Object>
, or if randomDetails
must be a plain old Map
without additional type information, then it's necessary to implement custom deserialization processing, as described in the user guide. (This is a situation where Gson unfortunately does not currently automatically generate Java values of String
or primitive type from JSON primitives, if the declared Java type is simply Object
. Thus it's necessary to implement the custom deserialization.)
Here's one such example.
import java.io.FileReader;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import com.google.gson.FieldNamingPolicy;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;
import com.google.gson.JsonPrimitive;
import com.google.gson.annotations.SerializedName;
public class Foo
{
public static void main(String[] args) throws Exception
{
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES);
gsonBuilder.registerTypeAdapter(MyClass.class, new MyClassDeserializer());
Gson gson = gsonBuilder.create();
MyClass myObject = gson.fromJson(new FileReader("input.json"), MyClass.class);
System.out.println(gson.toJson(myObject));
}
}
class MyClassDeserializer implements JsonDeserializer<MyClass>
{
@Override
public MyClass deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
throws JsonParseException
{
JsonObject object = json.getAsJsonObject();
String nickName = object.get("handle").getAsString();
Set<Map.Entry<String, JsonElement>> mapEntries = object.get("random_details").getAsJsonObject().entrySet();
Map randomDetails = new HashMap(mapEntries.size());
for (Map.Entry<String, JsonElement> mapEntry : mapEntries)
{
String key = mapEntry.getKey();
Object value;
JsonPrimitive jsonPrimitive = mapEntry.getValue().getAsJsonPrimitive();
if (jsonPrimitive.isNumber()) value = jsonPrimitive.getAsNumber();
else if (jsonPrimitive.isBoolean()) value = jsonPrimitive.getAsBoolean();
else value = jsonPrimitive.getAsString();
randomDetails.put(key, value);
}
MyClass myObject = new MyClass();
myObject.nickName = nickName;
myObject.randomDetails = randomDetails;
return myObject;
}
}
class MyClass
{
@SerializedName("handle")
String nickName;
Map randomDetails;
}
精彩评论