Java A类声明多个JSON字段
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/16476513/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
class A declares multiple JSON fields
提问by Java Questions
i have a class A which has some private fields and the same class extends another class B which also has some private fields which are in class A.
我有一个 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
}
and class B has got some private fiedls which are in class A
和 B 班有一些 A 班的私人领域
now when i try to create JSON string from above class A i get the following exception :
现在,当我尝试从 A 类上方创建 JSON 字符串时,出现以下异常:
class com.hexgen.ro.request.A declares multiple JSON fields named netAmountPcy
How to fix this?
如何解决这个问题?
Since they are private fields there should not be any problem while creating json string i guess but i am not sure.
由于它们是私有字段,因此在创建 json 字符串时应该没有任何问题,我猜但我不确定。
i create json string like the following :
我创建如下 json 字符串:
Gson gson = new Gson();
tempJSON = gson.toJson(obj);
here obj is the object of class A
这里 obj 是 A 类的对象
采纳答案by gerrytan
Since they are private fields there should not be any problem while creating json string
由于它们是私有字段,因此在创建 json 字符串时应该没有任何问题
I don't think this statement is true, GSON looks up at the object's private fields when serializing, meaning all private fields of superclass are included, and when you have fields with same name it throws an error.
我不认为这种说法是正确的,GSON 在序列化时会查找对象的私有字段,这意味着包含超类的所有私有字段,并且当您有同名的字段时,它会引发错误。
If there's any particular field you don't want to include you have to mark it with transient
keyword, eg:
如果您不想包含任何特定字段,则必须使用transient
关键字对其进行标记,例如:
private transient BigDecimal tradeFeesPcy;
回答by Adrian Lee
This is a bit late, but I ran into this exact same problem as well. The only thing was that I wasn't able to modify the superclass as that code wasn't mine. The way that I resolved this was by creating an exclusion strategy that skipped any field that had a field of the same name present in a superclass. Here is my code for that class:
这有点晚了,但我也遇到了完全相同的问题。唯一的问题是我无法修改超类,因为该代码不是我的。我解决这个问题的方法是创建一个排除策略,跳过任何在超类中存在同名字段的字段。这是我为该课程编写的代码:
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;
}
}
}
I then set the Serialization and Deserialization exclusion strategies in the builder as follows:
然后我在构建器中设置序列化和反序列化排除策略如下:
builder.addDeserializationExclusionStrategy(new SuperclassExclusionStrategy());
builder.addSerializationExclusionStrategy(new SuperclassExclusionStrategy());
Hopefully this helps someone!
希望这对某人有所帮助!
回答by RominaV
In my case I was dumb enough to register an adapter with X class, and try to serialize fromJson with Y class:
在我的例子中,我愚蠢到用 X 类注册一个适配器,并尝试用 Y 类序列化 fromJson:
final GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapter(Game.class, new TournamentSerializer());
final Gson gson = gsonBuilder.create();
createdTournament = gson.fromJson(jsonResponse.toString(), Tournament.class);
回答by Gangnus
The same error message also happens if you have different fields, but they have the same @SerializedName
.
如果您有不同的字段,但它们具有相同的@SerializedName
.
@SerializedName("date_created")
private Date DateCreated;
@SerializedName("date_created")
private Integer matchTime;
Doing copy/paste you can simply make such mistake. So, look into the the class and its ancestorsand check for that.
做复制/粘贴你可以简单地犯这样的错误。因此,查看该类及其祖先并检查它。
回答by Sujay
Add following lines at the bottom of proguard.config (if you are using proguard in project)
在 proguard.config 的底部添加以下行 (如果您在项目中使用 proguard)
-keepclassmembers class * {
private <fields>;
}
回答by Rafael Ruiz Mu?oz
Solution for Kotlin, as suggested @Adrian-Lee, you have to tweak some Null Checks
Kotlin 的解决方案,如@Adrian-Lee 建议的那样,您必须调整一些空检查
class SuperclassExclusionStrategy : ExclusionStrategy {
override fun shouldSkipClass(clazz: Class<*>?): Boolean {
return false
}
override fun shouldSkipField(f: FieldAttributes?): Boolean {
val fieldName = f?.name
val theClass = f?.declaringClass
return isFieldInSuperclass(theClass, fieldName)
}
private fun isFieldInSuperclass(subclass: Class<*>?, fieldName: String?): Boolean {
var superclass: Class<*>? = subclass?.superclass
var field: Field?
while (superclass != null) {
field = getField(superclass, fieldName)
if (field != null)
return true
superclass = superclass.superclass
}
return false
}
private fun getField(theClass: Class<*>, fieldName: String?): Field? {
return try {
theClass.getDeclaredField(fieldName)
} catch (e: Exception) {
null
}
}
}
回答by oziomajnr
I don't think you should make the members transient, this might lead to errors because members that you might need in the future might be hidden.
我不认为你应该让成员变得短暂,这可能会导致错误,因为你将来可能需要的成员可能会被隐藏。
How I solved this problem is to use a custom naming strategy and append the full class name to the Json, the downside of this is that it would lead to larger Json and if you need it for something like a Rest Api it would be weird for clients to name the fields that way, but I only needed to serialize to write to disk on android.
我解决这个问题的方法是使用自定义命名策略并将完整的类名附加到 Json,这样做的缺点是它会导致更大的 Json,如果您需要它来用于 Rest Api 之类的东西,这对于客户端以这种方式命名字段,但我只需要序列化即可在 android 上写入磁盘。
So here is an implementation of a custom naming strategy in Kotlin
所以这里是在 Kotlin 中实现自定义命名策略
import com.google.gson.FieldNamingStrategy
import java.lang.reflect.Field
class GsonFieldNamingStrategy : FieldNamingStrategy {
override fun translateName(field: Field?): String? {
return "${field?.declaringClass?.canonicalName}.${field?.name}"
}
}
So for all fields, the full canonical name would be appended, this would make the child class have a different name from the parent class, but when deserializing, the child class value would be used.
因此,对于所有字段,将附加完整的规范名称,这将使子类具有与父类不同的名称,但在反序列化时,将使用子类值。
回答by Saif Masadeh
I used GsonCBuilder
and ExclusionStrategy
to avoid the redundant fields as below, it is simple and straight forward.
我使用GsonCBuilder
并ExclusionStrategy
避免了如下冗余字段,它简单而直接。
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();