首页 > 解决方案 > 使用 Gson 反序列化 LocalDate 的问题

问题描述

我正在使用 Apache Camel 将我的 CSV 数据转换为 JSON 格式。然后我将它一个一个地流式传输到 ActiveMQ 主题,我的消费者(用 Spring Boot 编写)监听主题解析 JSON 并将其转换为相应的 POJO。

代码(生产者):

final BindyCsvDataFormat bindy = new BindyCsvDataFormat(camelproject.EquityFeeds.class);
        ConnectionFactory connectionFactory = new ActiveMQConnectionFactory("tcp://localhost:61616");
        CamelContext _ctx = new DefaultCamelContext(); 
        _ctx.addComponent("jms", JmsComponent.jmsComponentAutoAcknowledge(connectionFactory));
        _ctx.addRoutes(new RouteBuilder() {

            public void configure() throws Exception {
                from("file:src/main/resources?fileName=sampledata.csv")
                .unmarshal(bindy)
                .split(body())
                .marshal()
                .json(JsonLibrary.Jackson)
                .to("file:src/main/resources/?fileName=emp.txt")
                .split().tokenize("},").streaming().to("jms:queue:json.upstream.queue");            
            }

        });

我的 POJO 的相关部分:

@CsvRecord(separator = ",",skipFirstLine = true)
public class EquityFeeds implements Serializable {

    @DataField(pos = 1) 
    private String externalTransactionId;

    @DataField(pos = 2, pattern = "dd/MM/yy")
    private LocalDate transactionDate;

    // other fields and getters setters. 

}

我的数据(JSON 输出)像这样进入 ActiveMQ 主题:

{"externalTransactionId":"SAPEXTXN6","clientId":"AP","securityId":"ICICI","transactionType":"SELL","transactionDate":{"year":2013,"month":"NOVEMBER","dayOfMonth":25,"monthValue":11,"dayOfYear":329,"leapYear":false,"chronology":{"id":"ISO","calendarType":"iso8601"},"dayOfWeek":"MONDAY","era":"CE"},"marketValue":100.0,"sourceSystem":"BLO","priorityFlag":"Y","processingFee":0}

现在,当我对数据进行脱轨时,我希望 transactionDate 采用以下格式:YYYY-MM-DD

在我的消费者方面(在 Spring Boot 中编写的侦听器)我将 JSON 脱轨,如下所示:

if(jsonMessage instanceof TextMessage) {
            TextMessage textMessage = (TextMessage) jsonMessage;
            try {
                jsMessage =  textMessage.getText();
            } catch (JMSException e) {
                e.printStackTrace();
            }

        Gson gson = new Gson();
        EquityFeeds equityFeeds = gson.fromJson(jsMessage, EquityFeeds.class);

当我有 LocalDate 时,我无法正确反序列化我的 JSON 数据。

我得到以下异常:

com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected a string but was BEGIN_OBJECT at line 1 column 118 path $.transactionDate

然后我对代码进行了一些更改:

@CsvRecord(separator = ",",skipFirstLine = true)
public class EquityFeedsJson implements Serializable {

    @DataField(pos = 1) 
    private String externalTransactionId;   

    @DataField(pos = 2, pattern = "dd/MM/yy")
    @JsonSerialize(using = LocalDateSerializer.class)
    private LocalDate transactionDate;

    // other getters and setters and fields. 

}

LocalDateSerializer(代码):

public class LocalDateSerializer extends StdSerializer<LocalDate> {

    public LocalDateSerializer() {
        super(LocalDate.class);
    }

    @Override
    public void serialize(LocalDate value, JsonGenerator generator, SerializerProvider provider) throws IOException {
        generator.writeString(value.format(DateTimeFormatter.ISO_LOCAL_DATE));
    }
}

我的 JSON 现在是:

{"externalTransactionId":"SAPEXTXN6","clientId":"AP","securityId":"ICICI","transactionType":"SELL","transactionDate":"2013-11-25","marketValue":100.0,"sourceSystem":"BLO","priorityFlag":"Y","processingFee":0}

我在消费者端对其进行了反序列化:

 @JsonDeserialize(using = LocalDateDeserializer.class)
    private LocalDate transactionDate;

LocalDateDeserailizer 代码:

public class LocalDateDeserializer extends StdDeserializer<LocalDate> {

    protected LocalDateDeserializer() {
        super(LocalDate.class);
    }

    @Override
    public LocalDate deserialize(JsonParser parser, DeserializationContext context) throws IOException {
        return LocalDate.parse(parser.readValueAs(String.class));
    }
}

但同样的错误:

com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was STRING at line 1 column 118 path $.transactionDate

我该如何解决这个问题?我需要帮助。我需要使用 LocalDate 并能够使用 Gson 在消费者端反序列化。另请注意,在发布者端,我使用的是 Apache Camel,而在订阅者端,我使用 Gson 进行反序列化。我需要日期格式为:YYYY-MM-DD。

标签: javajsongsonjson-deserializationlocaldate

解决方案


推荐阅读