Gson:为类或字段

时间:2015-09-22 23:45:46

标签: java json gson

我不幸地解析了不同命名策略共存的JSON数据。

{
  "camelCaseData" : {
    "someField" : 1
  },
  "snake_case_data" : {
    "some_field" : 2
  }
}

是否可以为整个snakeCaseData指定命名政策?或者另一种有助于避免@SerializedName手动注释每个字段的解决方案?

如下所示

class Data {
  CamelCaseData camelCaseData;

  @GsonNamingPolicy(com.google.gson.FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES )
  SnakeCaseData snakeCaseData;
}

1 个答案:

答案 0 :(得分:3)

我无法确切地了解您所要求的内容,但我认为无论如何这可能会对您有所帮助。基本上,这将要求您注释任何只包含snake-case字段的类,以及包含camel-case字段的类中的任何snake-case字段。

首先我们定义一个你建议的注释:

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.TYPE})
public @interface GsonNamingPolicy {
    FieldNamingPolicy value();
}

然后我们将如上所述注释类:

public static class CamelCaseData {
    int someField;
}

@GsonNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES)
public static class SnakeCaseData {
    int someField;
}

public static class Data {
    CamelCaseData camelCaseData;

    @GsonNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES)
    SnakeCaseData snakeCaseData;
}

最后,我们定义了一个自定义FieldNamingStrategy,它检查字段及其声明类以获取新注释。如果存在注释,则使用注释中定义的策略,否则它仅使用默认策略。

public static class AnnotationFieldNamingStrategy implements FieldNamingStrategy {
    public String translateName(Field field) {
        Class<?> declaringClass = field.getDeclaringClass();

        GsonNamingPolicy fieldNamingPolicy = field.getAnnotation(GsonNamingPolicy.class);
        GsonNamingPolicy classNamingPolicy = declaringClass.getAnnotation(GsonNamingPolicy.class);

        FieldNamingPolicy policy = FieldNamingPolicy.IDENTITY;

        if (fieldNamingPolicy != null) {
            policy = fieldNamingPolicy.value();
        } else if (classNamingPolicy != null) {
            policy = classNamingPolicy.value();
        }

        return policy.translateName(field);
    }
}

然后,您可以在配置Gson时使用此策略:

    Gson gson = new GsonBuilder()
            .setFieldNamingStrategy(new AnnotationFieldNamingStrategy())
            .create();

    Data data = gson.fromJson(json, Data.class);

    System.out.println(data.camelCaseData.someField);
    System.out.println(data.snakeCaseData.someField);

这不完全是你所要求的,但无论如何它希望它对你有所帮助。我不相信有一种方法可以检查字段是否在声明它的类之外的级别进行注释。可能有一种方法可以实现您的目标,但可能需要使用自定义TypeAdapterTypeAdapterFactory