【问题标题】:How do I configure Genson to deserialize dates?如何配置 Genson 以反序列化日期?
【发布时间】:2019-04-07 13:01:22
【问题描述】:

我正在开发一个 Java servlet,我需要将一个类序列化和反序列化为 JSON 并返回。为此,我使用了 Genson 库,但遇到了问题。

Genson 无法反序列化 Date 类 (java.sql.Date) 的实例

我尝试设置自定义日期格式化程序,但它们似乎不影响反序列化。

我还尝试使用构建器调用 withConverter() 插入新转换器,但我无法弄清楚参数是如何工作的。

这是我目前的建设者电话

Genson genson = builder.setSkipNull(true).create();

我正在序列化的类有一个 Date 类型的字段

private Date introDate;

这是我尝试反序列化生成的 JSON 时发生的堆栈跟踪的 sn-p

Caused by: com.owlike.genson.JsonBindingException: Could not access value of property named 'hours' using accessor public int java.sql.Date.getHours() from class java.sql.Date
    at com.owlike.genson.reflect.PropertyAccessor.couldNotAccess(PropertyAccessor.java:40)
    at com.owlike.genson.reflect.PropertyAccessor$MethodAccessor.access(PropertyAccessor.java:70)
    at com.owlike.genson.reflect.PropertyAccessor.serialize(PropertyAccessor.java:24)
    at com.owlike.genson.reflect.BeanDescriptor.serialize(BeanDescriptor.java:92)
    at com.owlike.genson.convert.NullConverterFactory$NullConverterWrapper.serialize(NullConverterFactory.java:69)
    at com.owlike.genson.reflect.PropertyAccessor.serialize(PropertyAccessor.java:27)
    ... 38 more

这里的问题是像 getHours() 这样的方法已被弃用,因此调用它们会产生 IllegalArgumentException。我暂时不知道如何解决这个问题。

【问题讨论】:

  • 您使用 sql 日期对象有什么特别的原因吗?
  • 不知道 Genson,在所有其他条件相同的情况下,您不应该使用 java.sql.Date。该课程设计不良且早已过时。而是使用来自java.time, the modern Java date and time APILocalDate
  • java.sql.Date 类在几年前被 java.time.LocalDate 取代。查看 Genson 是否支持 Java 8 及更高版本中内置的 java.time 类 (JSR 310)。
  • 是的,我实际上在切换到 java.sql.Date 之前尝试了 LocalDate。而且它不适用于 Genson,因为它没有可以调用的公共构造函数来初始化对象。
  • @AlfaKhrisna 查看文档,其中有很多关于如何注册自定义转换器的示例和说明。最新版本还附带a bundle for java.time

标签: java json date genson


【解决方案1】:

您可以使用 java.util.Date。这适用于 Genson。

如果我们坚持使用 java.sql.Date,那么您可以编写自己的转换器并让 Genson 使用它。

让我们从 ser/deser 的对象开始:

import java.sql.Date;
import lombok.Getter;
import lombok.Setter;

public class CrashTestDummy {
    @Getter @Setter private String name;
    @Getter @Setter private Date sqlDate;

    /** Default no-arg constructor */
    public CrashTestDummy() {
    }
}

然后我们可以告诉 Genson 使用自定义转换器。在这种情况下,我将其转换为 Long in epoch 时间并再次返回。您可能会决定改用特定的日期格式。

import java.sql.Date;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import org.junit.Test;
import com.owlike.genson.Context;
import com.owlike.genson.Converter;
import com.owlike.genson.Genson;
import com.owlike.genson.GensonBuilder;
import com.owlike.genson.stream.ObjectReader;
import com.owlike.genson.stream.ObjectWriter;

    @Test
    public void serialiseDate() throws ParseException {
        // create a converter for java.sql.Date
        Converter<Date> converter = new Converter<Date>() {
            @Override
            public void serialize(Date obj, ObjectWriter writer, Context ctx) throws Exception {
                // java.sql.Date doesn't support any time fields, so we can just focus on y, M and d
                if(obj == null) {
                    writer.writeNull();
                    return;
                }
                writer.writeValue(  obj.getTime() );
            }

            @Override
            public Date deserialize(ObjectReader reader, Context ctx) {
                Long value = reader.valueAsLong();
                Date sqlDate = new java.sql.Date( value );
                return sqlDate;
            }
        };

        // Build a new Genson object with our converter
        Genson genson = new GensonBuilder()
                .setSkipNull(true)
                .withConverter(converter, java.sql.Date.class)
                .create();

        // make an important SQL date for testing
        java.util.Date utilDate = new SimpleDateFormat("dd MMM yyyy").parse("30 July 1966");
        Date sqlDate = new Date(utilDate.getTime() );

        // Make something to serialise
        CrashTestDummy original = new CrashTestDummy();
        original.setName( "Alfa Khrisna" );
        original.setSqlDate( sqlDate );

        // Call Genson as usual
        String json = genson.serialize( original );
        System.out.println( json );

        // Deserialise as usual; for brevity I'm comparing dates in millis since epoch.
        CrashTestDummy clone = genson.deserialize(json, CrashTestDummy.class);
        assertEquals(new SimpleDateFormat("dd MMM yyyy").parse("30 July 1966").getTime(), clone.getSqlDate().getTime());
        assertEquals("Alfa Khrisna", clone.getName());
    }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-03-22
    • 2021-10-27
    • 1970-01-01
    • 2021-07-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多