GSON java如何在映射和打印之间使用不同的名称?
我有这样一个JSON:GSON java如何在映射和打印之间使用不同的名称?,java,android,json,gson,Java,Android,Json,Gson,我有这样一个JSON: { "aggregation": { "CityAgg" : { "key" : "Paris" } } } Gson gson = new Gson(); Query2 query2 = gson.fromJson(response, Query2.class); 我创建映射,并为每个字段添加一个@SerializedName,因为我想为变量创建自定义名称 例如,在JSON中,有一个键名key,但我希望Java中的变量是cityN
{
"aggregation": {
"CityAgg" : {
"key" : "Paris"
}
}
}
Gson gson = new Gson();
Query2 query2 = gson.fromJson(response, Query2.class);
我创建映射,并为每个字段添加一个@SerializedName
,因为我想为变量创建自定义名称
例如,在JSON中,有一个键名key
,但我希望Java中的变量是cityName
因此,我这样做:
@SerializedName("key")
public String cityName
String query2String = gson.toJson(query2);
Gson gsonPretty = new GsonBuilder().setPrettyPrinting().create();
String prettyJson = gsonPretty.toJson(query2String);
我可以将响应JSON动态映射到我的对象,如下所示:
{
"aggregation": {
"CityAgg" : {
"key" : "Paris"
}
}
}
Gson gson = new Gson();
Query2 query2 = gson.fromJson(response, Query2.class);
它工作得很好
但是,当我要打印映射对象时,我会执行以下操作:
@SerializedName("key")
public String cityName
String query2String = gson.toJson(query2);
Gson gsonPretty = new GsonBuilder().setPrettyPrinting().create();
String prettyJson = gsonPretty.toJson(query2String);
问题是,在prettyJson
中,我可以看到键
,而不是cityName
我想知道是否有一种定制的方法。我不想看到键
或者应该使用a或者应该使用反射来更改注释的值
更新:最坏的解决方案
使用反射看起来像这样
ClassLoader classLoader = URLClassLoader.newInstance(new URL[]{YourClass.class.getResource("YourClass.class")});
Class locAnnotation = classLoader.loadClass("yourPackage.Query2");
Field field = locAnnotation.getDeclaredField("cityName");
final Annotation fieldAnnotation = field.getAnnotation(SerializedName.class);
changeAnnotationValue(fieldAnnotation, "oldValue", "newValue");
public static Object changeAnnotationValue(Annotation annotation, String key, Object newValue) {
Object handler = Proxy.getInvocationHandler(annotation);
Field f;
try {
f = handler.getClass().getDeclaredField("memberValues");
} catch (NoSuchFieldException | SecurityException e) {
throw new IllegalStateException(e);
}
f.setAccessible(true);
Map<String, Object> memberValues;
try {
memberValues = (Map<String, Object>) f.get(handler);
} catch (IllegalArgumentException | IllegalAccessException e) {
throw new IllegalStateException(e);
}
Object oldValue = memberValues.get(key);
if (oldValue == null || oldValue.getClass() != newValue.getClass()) {
throw new IllegalArgumentException();
}
memberValues.put(key, newValue);
return oldValue;
}
ClassLoader ClassLoader=URLClassLoader.newInstance(新URL[]{YourClass.class.getResource(“YourClass.class”)});
Class locAnnotation=classLoader.loadClass(“yourPackage.Query2”);
Field=locAnnotation.getDeclaredField(“cityName”);
final Annotation fieldAnnotation=field.getAnnotation(SerializedName.class);
changeAnnotationValue(字段注释,“旧值”、“新值”);
公共静态对象changeAnnotationValue(注释注释、字符串键、对象newValue){
对象处理程序=Proxy.getInvocationHandler(注释);
字段f;
试一试{
f=handler.getClass().getDeclaredField(“memberValues”);
}catch(NoSuchFieldException | SecurityException e){
抛出新的非法状态异常(e);
}
f、 setAccessible(true);
映射成员值;
试一试{
memberValues=(Map)f.get(handler);
}捕获(IllegalArgumentException | IllegalAccessException e){
抛出新的非法状态异常(e);
}
对象oldValue=memberValues.get(键);
如果(oldValue==null | | oldValue.getClass()!=newValue.getClass()){
抛出新的IllegalArgumentException();
}
memberValues.put(key,newValue);
返回旧值;
}
如果您不想像前面提到的那样编写自定义序列化器/反序列化器类,您可以始终创建某种类型的DTO对象
您的域类:
class CityAgg {
@SerializedName("key")
protected String cityName;
public String getCityName() {
return cityName;
}
}
class Aggregation {
@SerializedName("CityAgg")
protected CityAgg cityAgg;
public CityAgg getCityAgg() {
return cityAgg;
}
}
class Query2 {
@SerializedName("aggregation")
protected Aggregation aggregation;
public Aggregation getAggregation() {
return aggregation;
}
}
DTO类示例:
class CityAggDto {
protected String cityName;
public CityAggDto(CityAgg query2) {
this.cityName = query2.getCityName();
}
}
样本使用:
String response = "{ \"aggregation\": { \"CityAgg\": { \"key\": \"value\" } } }";
Gson gson = new Gson();
Gson gsonPretty = new GsonBuilder().setPrettyPrinting().create();
Query2 query2 = gson.fromJson(response, Query2.class);
CityAggDto cityAggDto = new CityAggDto(query2.getAggregation().getCityAgg());
String cityAggDtoJson = gson.toJson(cityAggDto);
String cityAggDtoPrettyJson = gsonPretty.toJson(cityAggDto);
Log.d(TAG, "onCreate: " + cityAggDtoJson);
Log.d(TAG, "onCreate: " + cityAggDtoPrettyJson);
结果:
@SerializationName
注释用于两种操作—序列化和反序列化—这就是JSON字符串包含key
key的原因
令人遗憾的是,尽管@SerializationName
注释可以与方法一起使用,但对getter和setter使用不同的值将不起作用,因为GSON仅基于字段:
使用字段vs getter指示Json元素
一些Json库使用类型的getter来推断Json元素。我们选择使用所有非瞬时、静态或合成的字段(继承层次结构上)。我们这样做是因为并非所有类都使用适当命名的getter编写。此外,getXXX或isXXX可能是语义的,而不是指示属性
然而,也有很好的参数支持属性。我们打算在后一个版本中增强Gson,以支持属性作为指示Json字段的替代映射。目前,Gson是基于字段的
资料来源:
这就是我改用杰克逊的原因。:) 使用也可以work@RC. 没有调用任何注释alternate@RC. 我这样做了:@SerializedName(value=“CityAgg”,alternate=“city”),但我仍然可以看到
CityAgg
正在被加密,而不是city
@AniaDavid简单的hack是在PrettyPrint()
过程中更改注释值,然后在使用…:)使用Reflection@RC. 听起来alternate不适合打印,谢谢你也能提供解决方案吗?你提供的答案我找不到soltin。