Как настроить Genson для десериализации дат? - PullRequest
1 голос
/ 07 апреля 2019

Я работаю над сервлетом Java, и мне нужно сериализовать и десериализовать класс в JSON и обратно.Для этого я использую библиотеку Genson, но попадаю в ловушку.

Genson не удается десериализовать экземпляры класса Date (java.sql.Date)

Я попытался установитьпользовательские форматеры даты, но они, похоже, не влияют на десериализацию.

Я также пытался подключить новые конвертеры с помощью вызова компоновщика withConverter (), но я не могу понять, как работают параметры.

Вот мой вызов конструктора на данный момент

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

Класс, который я сериализую, имеет поле типа Дата

private Date introDate;

Это фрагмент трассировки стека.это происходит, если я пытаюсь десериализовать полученный JSON

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.Я не знаю, как обойти это в данный момент.

1 Ответ

1 голос
/ 14 апреля 2019

Вы можете использовать java.util.Date. Это работает с Генсоном.

Если мы придерживаемся 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() {
    }
}

Тогда мы можем сказать Генсону использовать собственный конвертер. В этом случае я конвертирую его в длинную эпоху и обратно. Вместо этого вы можете использовать определенный формат даты.

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