Как правильно сериализовать / десериализовать java.time.DayOfWeek с Джексоном? - PullRequest
0 голосов
/ 17 февраля 2019

Я работаю над приложением, которое хранит день события.Я использую java.time.DayOfWeek для представления этого дня и сохраняю его в виде строки (например, MONDAY, WEDNESDAY).

Джексон сериализует этот тип как строку, поэтому представление JSON выглядит следующим образомзначение хранится в базе данных.Однако я хочу вместо этого сериализовать / десериализовать его как числовое значение.

Я попытался использовать @JsonFormat, но доступная числовая форма основана на индексе, что нежелательно, так как значение MONDAYэто 1, а не 0.

Написание нестандартного сериализатора кажется единственным решением здесь, но у меня есть ощущение, что эта проблема как-то решалась раньше.

Ответы [ 2 ]

0 голосов
/ 18 февраля 2019

Чтобы избежать недопонимания между слоями и частями приложения, лучше всего использовать String представление: MONDAY, WEDNESDAY и т. Д. Если вы хотите сериализовать это enum как int, любое число в порядкеи как же хорошо.На каждом слое вам нужно хранить информацию, что 1 равно MONDAY.Будет ли это 0, 1 или 10, не имеет значения.В Java мы имеем Calendar.MONDAY, равный 2, DayOfWeek.MONDAY, равный 1, но также WeekFields.ISO, где MONDAY - первый день и WeekFields.SUNDAY_START, где SUNDAY - первый деньнедели.

Если вам нужно определить 1 для MONDAY как общую идею для всех POJO классов, вам необходимо зарегистрировать пользовательский сериализатор.Пользовательский сериализатор может выглядеть следующим образом:

class DayOfWeekSerializer extends StdSerializer<DayOfWeek> {

    public DayOfWeekSerializer() {
        super(DayOfWeek.class);
    }

    @Override
    public void serialize(DayOfWeek value, JsonGenerator gen, SerializerProvider provider) throws IOException {
        gen.writeNumber(value.getValue());
    }
}

Пользовательский десериализатор:

class DayOfWeekDeserializer extends StdDeserializer<DayOfWeek> {

    public DayOfWeekDeserializer() {
        super(DayOfWeek.class);
    }

    @Override
    public DayOfWeek deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {
        return DayOfWeek.of(p.getIntValue());
    }
}

Вы можете зарегистрировать их, как показано ниже:

ObjectMapper createObjectMapper() {
    SimpleModule dayOfWeeModule = new SimpleModule("DayOfWeek module");
    dayOfWeeModule.addSerializer(DayOfWeek.class, new DayOfWeekSerializer());
    dayOfWeeModule.addDeserializer(DayOfWeek.class, new DayOfWeekDeserializer());

    ObjectMapper mapper = new ObjectMapper();
    mapper.registerModule(dayOfWeeModule);
    mapper.enable(SerializationFeature.INDENT_OUTPUT);

    return mapper;
}

Для проверки ниже POJO class:

class Days {

    private DayOfWeek monday = DayOfWeek.MONDAY;
    private DayOfWeek tuesday = DayOfWeek.TUESDAY;
    private DayOfWeek wednesday = DayOfWeek.WEDNESDAY;
    private DayOfWeek thursday = DayOfWeek.THURSDAY;
    private DayOfWeek friday = DayOfWeek.FRIDAY;
    private DayOfWeek saturday = DayOfWeek.SATURDAY;
    private DayOfWeek sunday = DayOfWeek.SUNDAY;

    // getter, setters, toString
}

Пример использования: ObjectMapper mapper = createObjectMapper ();

String json = mapper.writeValueAsString(new Days());
System.out.println(json);
System.out.println(mapper.readValue(json, Days.class));

Над кодом напечатано:

{
  "monday" : 1,
  "tuesday" : 2,
  "wednesday" : 3,
  "thursday" : 4,
  "friday" : 5,
  "saturday" : 6,
  "sunday" : 7
}
Days{monday=MONDAY, tuesday=TUESDAY, wednesday=WEDNESDAY, thursday=THURSDAY, friday=FRIDAY, saturday=SATURDAY, sunday=SUNDAY}
0 голосов
/ 17 февраля 2019

Вы можете игнорировать метод получения по умолчанию и добавить другой метод, сопоставленный с вашим полем DayOfWeek.Для установщика вы можете сделать дополнительный установщик, который принимает int вместо перечисления.

Вот пример реализации:

class MyDate {

    private DayOfWeek dow = DayOfWeek.MONDAY;// DayOfWeek.of(LocalDate.now().getDayOfWeek());

    @JsonIgnore
    public DayOfWeek getDow() {
        return dow;
    }

    public void setDow(int dow) {
        this.dow = DayOfWeek.of(dow + 1);
    }

    @JsonProperty("dow")
    public int getDayOfWeekNumber() {
        return dow.getValue() - 1; //0 for Monday
    }

    public void setDow(DayOfWeek dow) {
        this.dow = dow;
    }

    @Override
    public String toString() {
        return "[dow=" + dow + "]";
    }

    public static void main(String[] args) throws Exception {
        System.out.println(new ObjectMapper().writeValueAsString(new MyDate()));
        System.out.println(new ObjectMapper().readValue("{\"dow\":7}", MyDate.class));
    }
}

DayOfWeek не поддерживаетнастройка первого дня недели или его индекса.Вот почему приведенный выше код использует +/- 1 для сдвига.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...