【问题标题】:Serialize objects to a map with the object class as the key?将对象序列化为以对象类为键的映射?
【发布时间】:2021-10-04 19:37:05
【问题描述】:

我正在编写一个使用 Spring boot 和 jackson 进行 JSON 解析的应用程序。我需要处理另一个生成 JSON 的服务,如下所示:

{
  "task-id": 5081,
  "task-created-on": {
    "java.util.Date": 1631022026000
  }
}

值得注意的是,这里的日期字段等某些字段被序列化为具有单个键值对的映射,其中键是 java 类名,值是字段的实际值。

我一直在浏览 jackson 文档,但没有找到任何关于这种格式的信息。有没有办法配置jackson以这种格式生成和解析字段?

至少,我需要处理这种格式的日期。但我相信该服务也将这种格式用于其他对象,其中映射键将是某个任意 java 类的名称,值将是它自己的映射。因此,如果可能的话,我会对处理不仅仅是日期的解决方案感兴趣。

【问题讨论】:

  • 避免误解的问题:task-created-on 是您的 pojo 中的 Date 字段,因此它通常会序列化为 "task-created-on": 1631022026000 ?
  • @dariosicily 是的,没错。如果可能,“task-created-on”应该是一个日期字段。

标签: java json jackson


【解决方案1】:

可以通过以下步骤在 Jackson 中使用 custom serializer 轻松完成。
首先,创建序列化对象如下:

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 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();
    }
}

最后,用ObjectMapperMyDateObject类注册序列化器并执行序列化:

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}}


更多信息请参考Jackson – Custom Serializer

【讨论】:

  • 谢谢,@LHCHIN。我选择了另一个答案,因为它更笼统。
  • 没关系!我没有注意到您想要一个通用的解决方案,所以我只是为您的原始问题提供一个简单的解决方案。 :)
【解决方案2】:

可以通过使用自定义 JsonSerializer 并将 JsonSerialize 应用于您感兴趣的 pojo 中的字段来解决问题,如下所示:

public class Task {

    @JsonProperty("task-id")
    private int taskId;

    @JsonProperty("task-created-on")
    @JsonSerialize(using = ObjectSerializer.class)
    Date taskCreatedOn; 
}

自定义序列化器将使用 JsonGenerator.html#writeObjectField 将通用对象(Date 或其他 java 类)序列化为属性名:{“类名”:值}:

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();
    }

}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-18
    • 1970-01-01
    • 1970-01-01
    • 2023-03-24
    • 1970-01-01
    相关资源
    最近更新 更多