Подтвердить что ты не робот

@IntDef Андронизация поддержки Android с десериализацией Джексона

Использование JacksonAnnotations вместе с аннотациями поддержки Android. Мой POJO:

@JsonIgnoreProperties(ignoreUnknown = true)
public class Schedule {
    public static final int SUNDAY = 0;
    public static final int MONDAY = 1;
    public static final int TUESDAY = 2;
    public static final int WEDNESDAY = 3;
    public static final int THURSDAY = 4;
    public static final int FRIDAY = 5;
    public static final int SATURDAY = 6;

    private Integer weekday;

    public Schedule() {
    }

    @Weekday
    public Integer getWeekday() {
        return weekday;
    }

    public void setWeekday(@Weekday Integer weekday) {
        this.weekday = weekday;
    }

    @Retention(RetentionPolicy.RUNTIME)
    @IntDef({SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY})
    public @interface Weekday {}
}

От поддержки я получаю объект:

{"schedule":{"weekday":"MONDAY"}}

То, что я хочу, - сопоставить день недели с ним целочисленным значением, определенным в константах. Есть ли способ достичь этого?

Обновить. Основная цель - оптимизация (. Вы должны строго избегать использования перечислений на Android, как сказано здесь).

4b9b3361

Ответ 1

Поскольку вы можете рассчитывать на то, что будни не выходят из-под контроля, создание статической карты кажется довольно чистым решением. Предоставление @JsonCreator factory с именем fromString будет работать с Jackson, а также отлично играть с JAX-RS:

public class Schedule {
    ...
    private static final ImmutableMap<String, Schedule> WEEKDAY_TO_INT_MAP =
            ImmutableMap.<String, Schedule>builder()
                .put("SUNDAY", withIntWeekday(0))
                .put("MONDAY", withIntWeekday(1))
                .put("TUESDAY", withIntWeekday(2))
                .put("WEDNESDAY", withIntWeekday(3))
                .put("THURSDAY", withIntWeekday(4))
                .put("FRIDAY", withIntWeekday(5))
                .put("SATURDAY", withIntWeekday(6))
                .build();

    public static Schedule withIntWeekday(int weekdayInt) {
        Schedule schedule = new Schedule();
        schedule.setWeekday(weekdayInt);
        return schedule;
    }

    @JsonCreator
    public static Schedule fromString(String weekday) {
        return WEEKDAY_TO_INT_MAP.get(weekday);
    }
    ...
}

Ответ 2

Может, мне чего-то не хватает, но почему бы не сделать что-то вроде этого:

public class Schedule {
    public enum Weekday {
        SUNDAY(0),
        MONDAY(1),
        TUESDAY(2),
        WEDNESDAY(3),
        THURSDAY(4),
        FRIDAY(5),
        SATURDAY(6);

        private final Integer weekday;

        Weekday(Integer weekday) {
            this.weekday = weekday;
        }

        public Integer getWeekday() {
            return weekday;
        }
    }

    private Weekday weekday;

    public Integer getWeekday() {
        return weekday.getWeekday();
    }

    public void setWeekday(Weekday weekday) {
        this.weekday = weekday;
    }

}

Ответ 3

Если backend возвращает "MONDAY" как строку, вы, вероятно, не должны использовать @IntDef, потому что вам придется управлять преобразованием "MONDAY" в целочисленное значение.

Я попытался бы использовать аннотацию @StringDef, вместо этого вам не придется беспокоиться о каком-либо преобразовании между бэкэнд и клиентским приложением. Единственный улов - вам нужно иметь надежные ответы от вашего бэкэнда и заранее согласовывать соглашения об именах.

Если вы измените тип с @IntDef на @StringDef, он будет выглядеть так:

@JsonIgnoreProperties(ignoreUnknown = true)
public class Schedule {
    public static final String SUNDAY = "SUNDAY";
    public static final String MONDAY = "MONDAY";
    public static final String TUESDAY = "TUESDAY";
    public static final String WEDNESDAY = "WEDNESDAY";
    public static final String THURSDAY = "THURSDAY";
    public static final String FRIDAY = "FRIDAY";
    public static final String SATURDAY = "SATURDAY";

    private String weekday;

    public Schedule() {
    }

    @Weekday
    public String getWeekday() {
        return weekday;
    }

    public void setWeekday(@Weekday String weekday) {
        this.weekday = weekday;
    }

    @Retention(RetentionPolicy.RUNTIME)
    @StringDef({SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY})
    public @interface Weekday {}
}

Ответ 4

Элегантное решение использует Enum.

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

Вы также можете получить доступ к значениям в аннотации StringDef, используя отражение в вашем сериализаторе, но это будет медленнее и менее читаемо.