A类声明多个JSON字段

Jav*_*ons 67 java json gson

我有一个类A,它有一些私有字段,同一个类扩展另一个类B,它也有一些私有字段在A类.

public class A extends B {
    private BigDecimal netAmountTcy;
    private BigDecimal netAmountPcy;   
    private BigDecimal priceTo;  
    private String segment;

    private BigDecimal taxAmountTcy;
    private BigDecimal taxAmountPcy;   
    private BigDecimal tradeFeesTcy;
    private BigDecimal tradeFeesPcy;

// getter and setter for the above fields

}
Run Code Online (Sandbox Code Playgroud)

而且B级有一些属于A级的私人fiedls

现在,当我尝试从类A上面创建JSON字符串时,我得到以下异常:

class com.hexgen.ro.request.A declares multiple JSON fields named netAmountPcy
Run Code Online (Sandbox Code Playgroud)

如何解决这个问题?

因为它们是私有字段,所以在创建json字符串时应该没有任何问题我猜,但我不确定.

我创建json字符串,如下所示:

Gson gson = new Gson();
 tempJSON = gson.toJson(obj);
Run Code Online (Sandbox Code Playgroud)

这里obj是A类的对象

ger*_*tan 70

由于它们是私有字段,因此在创建json字符串时应该没有任何问题

我不认为这个陈述是正确的,GSON在序列化时会查看对象的私有字段,这意味着包含了所有超类的私有字段,并且当你有相同名称的字段时会抛出错误.

如果您不希望包含任何特定字段,则必须使用transient关键字对其进行标记,例如:

private transient BigDecimal tradeFeesPcy;
Run Code Online (Sandbox Code Playgroud)

  • @Fakher要使@Expose正常工作,您需要设置`@Expose(serialize = false)`,并确保在您的`GsonBuilder`对象上调用`excludeFieldsWithoutExposeAnnotation()`。 (2认同)
  • 这个评论完美解决了我的问题。使用 ```new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create().toJson(YOUR_OBJECT)```,它可以工作 (2认同)

小智 61

这有点晚了,但我遇到了同样的问题.唯一的事情是我无法修改超类,因为该代码不是我的.我解决这个问题的方法是创建一个排除策略,跳过任何具有超类中存在的同名字段的字段.这是我的类的代码:

public class SuperclassExclusionStrategy implements ExclusionStrategy
{
    public boolean shouldSkipClass(Class<?> arg0)
    {
        return false;
    }

    public boolean shouldSkipField(FieldAttributes fieldAttributes)
    {
        String fieldName = fieldAttributes.getName();
        Class<?> theClass = fieldAttributes.getDeclaringClass();

        return isFieldInSuperclass(theClass, fieldName);            
    }

    private boolean isFieldInSuperclass(Class<?> subclass, String fieldName)
    {
        Class<?> superclass = subclass.getSuperclass();
        Field field;

        while(superclass != null)
        {   
            field = getField(superclass, fieldName);

            if(field != null)
                return true;

            superclass = superclass.getSuperclass();
        }

        return false;
    }

    private Field getField(Class<?> theClass, String fieldName)
    {
        try
        {
            return theClass.getDeclaredField(fieldName);
        }
        catch(Exception e)
        {
            return null;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

然后,我在构建器中设置序列化和反序列化排除策略,如下所示:

    builder.addDeserializationExclusionStrategy(new SuperclassExclusionStrategy());
    builder.addSerializationExclusionStrategy(new SuperclassExclusionStrategy());
Run Code Online (Sandbox Code Playgroud)

希望这有助于某人!

  • 在我看来,这是错误的方式.这样你的json将包含来自超类的变量,并且隐藏子类的值.人们会期望相反的方式; 在json中有子类变量,并隐藏超类变量. (11认同)
  • 这是正确的答案,因为我不想排除超类'对象被序列化,我只是不希望GSON排除扩展类'变量 (3认同)

Gan*_*nus 11

如果您有不同的字段,也会出现相同的错误消息,但它们具有相同的错误消息@SerializedName.

@SerializedName("date_created")
private Date DateCreated;
@SerializedName("date_created")
private Integer matchTime;
Run Code Online (Sandbox Code Playgroud)

复制/粘贴你可以简单地犯这样的错误.所以,看看班级及其祖先并检查一下.

  • 如果我的 JSON 文件确实具有相同的名称和不同的类型(故意)怎么办?即一些端点“main_id”是一个Int,一些其他端点“main_id”是一个String (2认同)

Suj*_*jay 7

在proguard.config的底部添加以下行 (如果您在项目中使用proguard)

-keepclassmembers class * {
    private <fields>;    
}
Run Code Online (Sandbox Code Playgroud)


REM*_*ode 6

在 kotlin 中,在父类上添加@Transient变量的注释对我来说在具有开放变量的类上起到了作用sealed


Sai*_*deh 5

我使用GsonBuilderExclusionStrategy避免了如下冗余字段,它简单而直接。

Gson json = new GsonBuilder()
          .setExclusionStrategies(new ExclusionStrategy() {
             @Override
             public boolean shouldSkipField(FieldAttributes f) {
                if(f.getName().equals("netAmountPcy")){
                   return true;
                }
                return false;
             }

             @Override
             public boolean shouldSkipClass(Class<?> clazz) {
                return false;
             }
          }).create();
Run Code Online (Sandbox Code Playgroud)