GSON - 反序列化不区分大小写的字段名称(没有明确的大小写模式)

时间:2016-03-18 10:00:14

标签: java gson

我想构建一个灵活的api,我没有明确的用户可以传递的区分大小写,所以GSON必须能够在区分大小写的情况下反序列化。

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

如何将这些字段反序列化为我的Foo的firstName?

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

我尝试使用FieldNamingPolicy,但它没有用。

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

3 个答案:

答案 0 :(得分:11)

有一种更简单的方式来获得你想要的东西。我没有意识到,但自从GSON 2.4以来,SerializedName注释支持GSON可以反序列化的备用名称数组。

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;
    }
}

您可以使用它来支持可能的变化,而无法处理类似" firSTNAme"。

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

看起来GSON没有一种简单的内置方式可以按照您的需要进行自定义。从技术上讲,你可以实现一个TypeAdapterFactory,它使用反射来做到这一点,但似乎过分了。

您可以向GSON打开一个功能请求,说明是否支持支持替代名称或模式或不区分大小写匹配的字段命名策略。

答案 1 :(得分:3)

不能完全解决此问题,但是如果键恰好都是小写字母,例如headimgurl,则可以实现FieldNamingStrategy接口

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

将值解析到对象的headImgUrl字段。

答案 2 :(得分:2)

我认为您需要实现自定义liquidation。 字段命名策略和策略似乎提供了一种将Java字段名称映射到JSON属性但不将JSON属性映射到Java字段名称的方法。

此反序列化器将忽略属性名称的大小写,并尝试将其与" firstname"匹配。

JsonDeserialiser

在构建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"); } } 对象时,可以将其注册为类型适配器:

Gson

然后调用如:

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

返回Foo对象的列表,每个对象的名字为Juan。

唯一的问题是为对象构建反序列化器可能会成为负担。您的解串器需​​要比上面的示例更复杂。