【发布时间】:2012-10-04 14:48:29
【问题描述】:
这是为所有 JSON 大脑准备的。
假设我有一个类似的界面:
public interface Model {
String getName();
String getDateCreated();
String getTimeCreated();
String getLastUpdated();
String getLastUpdatedTime();
}
那么假设我有一个 Item 对象:
public class Item {
private String name;
private Date created;
private Date updated;
..setters and getters
}
那么假设我有一个模型包装器:
public class ItemModel implements Model {
private final Item item;
public ItemModel(Item item){
this.item = item;
}
public String getName(){
return item.getName();
}
public String getDateCreated(){
Date created = item.getCreated();
//format the date nicely and return a date string
}
public String getTimeCreated(){
Date created = item.getCreated();
//format the date nicely and return a time string
}
...you get the gyst, right?
}
问题是:
- 如何序列化 ItemModel 以便 json 输出反映模型接口上的 getter 名称?
- 具体来说,哪个库最容易做到这一点?您如何使用特定的库来实现这一点?
- 最后,我不想序列化包装在 ItemModel 中的 Item 对象
我希望输出是这样的:
{item : {name: '', dateCreated : '', timeCreated : '', lastUpdated : '', lastUpdatedTime : ''}
提前致谢!
我认为我应该分享到目前为止我所能提供的内容,并获得您的反馈。它几乎可以满足我的要求,但我不确定它是否正确:
我在这里被一位用户指向了genson,我觉得它很有趣。
首先我创建了一个序列化器
公共类 ModelSerializer 实现序列化器 {
@Override
public void serialize(T target, ObjectWriter writer, Context cntxt) throws TransformationException, IOException {
writer.beginObject();
for (Method method : target.getClass().getMethods()) {
String methodName = method.getName();
if (methodName.startsWith("get")) {
int index = "get".length();
String valueName = Character.toLowerCase(methodName.charAt(index)) + method.getName().substring(index + 1);
try {
String valueString = (String) method.invoke(target, new Object[]{});
writer.writeName(valueName).writeValue(valueString);
} catch (IllegalArgumentException ex) {
Logger.getLogger(ModelSerializer.class.getName()).log(Level.SEVERE, null, ex);
throw new TransformationException(ex.getMessage());
} catch (IllegalAccessException ex) {
Logger.getLogger(ModelSerializer.class.getName()).log(Level.SEVERE, null, ex);
throw new TransformationException(ex.getMessage());
} catch (InvocationTargetException ex) {
Logger.getLogger(ModelSerializer.class.getName()).log(Level.SEVERE, null, ex);
throw new TransformationException(ex.getMessage());
}
}
}
writer.endObject();
}
}
接下来,我创建了 Genson 并通过了 Serializer
Genson genson = new Genson.Builder().withSerializer(new ModelSerializer(), Model.class).create();
现在,当我通过 ViewModel 时,我得到的字段格式符合我的预期
模型 viewModel = new ItemModel(domainModel);其中 domainModel 是 Item 的一个实例 System.out.println(genson.serialize(viewModel));
【问题讨论】:
-
很高兴您喜欢 Genson!但是你为什么要做所有内省的事情呢?您期望的确切输出是什么?您应该将您的 Serializer 定义为 ModelSerializer implements Serializer
{ ... class code ... } 然后只需将其注册为 Builder().withConverters(new ModelSerializer()).create(); -
你为什么不直接做 new Genson().serialize(viewModel); ?您将获得与自定义序列化程序相同的输出(我刚刚测试了两种解决方案)。
-
您是否注意到 Model 接口只返回字符串值,而 Item 返回字符串和日期?您必须对日期输出进行一些格式化,这是导致问题的原因。
-
是的,我注意到了,但是通过将@JsonIgnore 放在项目上,他将不会被序列化,并且只会使用来自 ItemModel 的 get 方法(使用您在这些方法中定义的格式)。这样做能解决你的问题吗?
-
啊,您可以定义您希望 genson 在序列化日期时使用的格式: Genson genson = new Genson.Builder().setDateFormat(yourDateFormat).create();