将对象序列化为以对象 class 为键的映射?
Serialize objects to a map with the object class as the key?
我正在编写一个应用程序,使用 Spring boot 和 jackson 进行 JSON 解析。我需要像这样处理另一个产生 JSON 的服务:
{
"task-id": 5081,
"task-created-on": {
"java.util.Date": 1631022026000
}
}
值得注意的是,某些字段(例如此处的日期字段)被序列化为具有单个键值对的映射,其中键是 java classname,值是实际值领域的。
我一直在浏览 jackson 文档,但没有找到任何关于这种格式的信息。有没有办法配置 jackson 来生成和解析这种格式的字段?
至少,我需要处理这种格式的日期。但我相信该服务也将这种格式用于其他对象,其中映射键将是任意 java class 的名称,而值将是它自己的映射。因此,如果可能的话,我会对处理的不仅仅是日期的解决方案感兴趣。
可以通过以下步骤在 Jackson 中使用 自定义序列化程序 轻松完成。
首先,创建序列化对象如下:
class MyDateObject {
private Date date;
//general getter/setter
}
class Task {
@JsonProperty("task-id")
private int taskId;
@JsonProperty("task-created-on")
private MyDateObject taskCreatedOn;
//general getters/setters
}
其次,定义您的自定义序列化程序:(请注意,我使用 myDateObject.getDate().getClass().getName()
获取日期字段的 class 名称。)
class DateSerializer extends StdSerializer<MyDateObject> {
public DateSerializer() {
this(null);
}
protected DateSerializer(Class<MyDateObject> t) {
super(t);
}
@Override
public void serialize(MyDateObject myDateObject, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
jsonGenerator.writeStartObject();
jsonGenerator.writeNumberField(myDateObject.getDate().getClass().getName(), myDateObject.getDate().getTime());
jsonGenerator.writeEndObject();
}
}
最后,用ObjectMapper
为MyDateObject
class注册序列化器并执行序列化:
MyDateObject myDateObject = new MyDateObject();
myDateObject.setDate(new Date());
Task task = new Task();
task.setTaskId(5081);
task.setTaskCreatedOn(myDateObject);
SimpleModule simpleModule = new SimpleModule();
simpleModule.addSerializer(MyDateObject.class, new DateSerializer());
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.registerModule(simpleModule);
System.out.println(objectMapper.writeValueAsString(task));
预期输出为:
{"task-id":5081,"task-created-on":{"java.util.Date":1633402076254}}
可以通过对您感兴趣的 pojo 中的字段使用自定义 JsonSerializer
and applying the JsonSerialize
来解决问题,如下所示:
public class Task {
@JsonProperty("task-id")
private int taskId;
@JsonProperty("task-created-on")
@JsonSerialize(using = ObjectSerializer.class)
Date taskCreatedOn;
}
自定义序列化程序将使用 JsonGenerator.html#writeObjectField
将通用对象(Date
或其他 java class)序列化为 propertyname : {"class名称”:值}:
public class ObjectSerializer extends JsonSerializer<Object> {
@Override
public void serialize(Object t, JsonGenerator jg, SerializerProvider sp) throws IOException {
jg.writeStartObject();
jg.writeObjectField(t.getClass().getName(), t);
jg.writeEndObject();
}
}
我正在编写一个应用程序,使用 Spring boot 和 jackson 进行 JSON 解析。我需要像这样处理另一个产生 JSON 的服务:
{
"task-id": 5081,
"task-created-on": {
"java.util.Date": 1631022026000
}
}
值得注意的是,某些字段(例如此处的日期字段)被序列化为具有单个键值对的映射,其中键是 java classname,值是实际值领域的。
我一直在浏览 jackson 文档,但没有找到任何关于这种格式的信息。有没有办法配置 jackson 来生成和解析这种格式的字段?
至少,我需要处理这种格式的日期。但我相信该服务也将这种格式用于其他对象,其中映射键将是任意 java class 的名称,而值将是它自己的映射。因此,如果可能的话,我会对处理的不仅仅是日期的解决方案感兴趣。
可以通过以下步骤在 Jackson 中使用 自定义序列化程序 轻松完成。
首先,创建序列化对象如下:
class MyDateObject {
private Date date;
//general getter/setter
}
class Task {
@JsonProperty("task-id")
private int taskId;
@JsonProperty("task-created-on")
private MyDateObject taskCreatedOn;
//general getters/setters
}
其次,定义您的自定义序列化程序:(请注意,我使用 myDateObject.getDate().getClass().getName()
获取日期字段的 class 名称。)
class DateSerializer extends StdSerializer<MyDateObject> {
public DateSerializer() {
this(null);
}
protected DateSerializer(Class<MyDateObject> t) {
super(t);
}
@Override
public void serialize(MyDateObject myDateObject, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
jsonGenerator.writeStartObject();
jsonGenerator.writeNumberField(myDateObject.getDate().getClass().getName(), myDateObject.getDate().getTime());
jsonGenerator.writeEndObject();
}
}
最后,用ObjectMapper
为MyDateObject
class注册序列化器并执行序列化:
MyDateObject myDateObject = new MyDateObject();
myDateObject.setDate(new Date());
Task task = new Task();
task.setTaskId(5081);
task.setTaskCreatedOn(myDateObject);
SimpleModule simpleModule = new SimpleModule();
simpleModule.addSerializer(MyDateObject.class, new DateSerializer());
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.registerModule(simpleModule);
System.out.println(objectMapper.writeValueAsString(task));
预期输出为:
{"task-id":5081,"task-created-on":{"java.util.Date":1633402076254}}
可以通过对您感兴趣的 pojo 中的字段使用自定义 JsonSerializer
and applying the JsonSerialize
来解决问题,如下所示:
public class Task {
@JsonProperty("task-id")
private int taskId;
@JsonProperty("task-created-on")
@JsonSerialize(using = ObjectSerializer.class)
Date taskCreatedOn;
}
自定义序列化程序将使用 JsonGenerator.html#writeObjectField
将通用对象(Date
或其他 java class)序列化为 propertyname : {"class名称”:值}:
public class ObjectSerializer extends JsonSerializer<Object> {
@Override
public void serialize(Object t, JsonGenerator jg, SerializerProvider sp) throws IOException {
jg.writeStartObject();
jg.writeObjectField(t.getClass().getName(), t);
jg.writeEndObject();
}
}