GSON - Deserialize case insensitive field name (no definite case pattern)

半世苍凉 提交于 2021-02-17 21:39:58

问题


I want to build a flexible api, I have no definite case sensitivity the user can pass, so GSON must be able to deserialize this in case sensitive.

{"firstName":"Juan"}
{"firstname":"Juan"}
{"Firstname":"Juan"}
...

How can I deserialize these field into my Foo's firstName?

public class Foo {
    private String firstName;
    //..getters
}

I tried to use FieldNamingPolicy, but it did not work.

new GsonBuilder()
            .setFieldNamingPolicy(FieldNamingPolicy.UPPER_CAMEL_CASE)
            .setPrettyPrinting()
            .create();

回答1:


There is an easier way to almost get what you want. I'd not realised but since GSON 2.4 the SerializedName annotation supports an array of alternate names that GSON can deserialise from.

public class Foo {
    @SerializedName(value = "firstName", alternate = {"firstname", "Firstname"})
    private String firstName;

    public java.lang.String getFirstName() {
        return firstName;
    }

    @Override
    public String toString() {
        return "Foo:" + firstName;
    }
}

You could use this to support the likely variations without being able to handle something like "firSTNAme".

https://google.github.io/gson/apidocs/com/google/gson/annotations/SerializedName.html

It doesn't look as though GSON has an easy built in way to customise it the way you want. It looks as though technically you could implement a TypeAdapterFactory that uses reflection to do this but it seems excessive.

You might open a feature request with GSON about introducing support for field naming strategies that support alternative names or pattern, or case insensitive matching.




回答2:


Not a complete solution to this problem but if the keys happen to be all lowercase such as headimgurl then you can implement FieldNamingStrategy interface

Gson gson = new GsonBuilder().setFieldNamingStrategy(f -> f.getName().toLowerCase()).create();

to parse the value to headImgUrl field of the object.




回答3:


I think you will need to implement a custom JsonDeserialiser. The field naming policy and strategy appears to provide a way to map Java field names to JSON properties but not JSON properties to Java field names.

This deserialiser will ignore the case of the name of the property and try to match it against "firstname".

public final class FooDeserialiser implements JsonDeserializer<Foo> {

    @Override
    public Foo deserialize(
        JsonElement jsonElement,
        Type type,
        JsonDeserializationContext jsonDeserializationContext)
        throws JsonParseException {

        for (Map.Entry<String, JsonElement> property : jsonElement.getAsJsonObject().entrySet()) {
            if ("firstname".equalsIgnoreCase(property.getKey())) {
                return new Foo(property.getValue().getAsString());
            }
        }
        // Or return null if you prefer, or return a Foo with null as the first name
        // It has failed to find any property that looks like firstname
        throw new JsonParseException("No firstName property");
    }
}

This can be registered as a type adapter with the Gson object when it is being built like this:

final Gson gson = new GsonBuilder()
        .registerTypeAdapter(Foo.class, new FooDeserialiser())
        .setPrettyPrinting()
        .create();

And then invoked like:

final List<Foo> foos = gson.fromJson(
        "[{\"firstName\":\"Juan\"},{\"firstname\":\"Juan\"},{\"Firstname\":\"Juan\"}]",
        new TypeToken<List<Foo>>() {}.getType());

To return a list for Foo objects each with the first name Juan.

The only problem is building the deserialisers for your objects may become a burden. Your deserialisers will need to be more complicated than the above example.



来源:https://stackoverflow.com/questions/36081359/gson-deserialize-case-insensitive-field-name-no-definite-case-pattern

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!