Прочитайте массив JSON как перечисления с типом, основанным на свойстве.JAVA

Программисты JAVA общаются здесь
Ответить Пред. темаСлед. тема
Anonymous
 Прочитайте массив JSON как перечисления с типом, основанным на свойстве.

Сообщение Anonymous »

Мой ввод в формате JSON:

Код: Выделить всё

{
// other fields
"context": [
{
"id": "age",
"name": "Age",
"type": "string",
"value": "730 days +"
},
{
"id": "v2Score",
"name": "V2 Score",
"type": "number",
"value": 5.9
},
{
"id": "maturity",
"name": "Maturity",
"type": "string",
"value": "High"
},
{
"id": "coverage",
"name": "Product Coverage",
"type": "string",
"value": "Low"
},
{
"id": "threat_intensity",
"name": "Threat Intensity",
"type": "string",
"value": "Very Low"
},
{
"id": "threat_recency",
"name": "Threat Recency",
"type": "string",
"value": "No recorded events"
},
{
"id": "threat_sources",
"name": "Threat Sources",
"type": "string",
"value": "No recorded events"
}
]
}
и мой контекст POJO-класс выглядит так

Код: Выделить всё

class Context {
private final Age age;
private final Maturity maturity;
private final Coverage coverage;
private final ThreatIntensity threatIntensity;
private final ThreatRecency threatRecency;

// constructor, getters
}
Все вышеперечисленные поля в контексте являются перечислениями. Использование возраста в качестве примера:

Код: Выделить всё

enum Age {
@JsonProperty("0 - 7 days")
LESS_THAN_ONE_WEEK,
@JsonProperty("7 - 30 days")
ONE_WEEK_TO_ONE_MONTH,
@JsonProperty("30 - 365 days")
ONE_MONTH_TO_ONE_YEAR,
@JsonProperty("365 - 730 days")
ONE_TO_TWO_YEARS,
@JsonProperty("730 days + ")
MORE_THAN_TWO_YEARS
}
объект в массиве с "id": "age" соответствует типу перечисления Age, а "value": "730 дней +"< /code> соответствует Age.MORE_THAN_TWO_YEARS.
Как десериализовать этот массив объектов в отдельные перечисления? Каждый объект в массиве соответствует ровно один тип перечисления (т. е. в массиве никогда не будет двух объектов с одинаковым идентификатором), но объекты в массиве не гарантированно будут каждый раз находиться в одном и том же порядке. Есть ли способ сделать это с помощью аннотаций, например @JsonTypeInfo? Кроме того, хотя я не ожидаю отсутствия каких-либо перечислений, мне хотелось бы иметь возможность передавать «отсутствующие» перечисления как null. Например, если объект с «id»: «maturity» не присутствовал в массиве, связанный объект перечисления Maturity должен быть десериализован как нулевой. До сих пор данные, возвращаемые из этого API, либо включали все эти элементы, либо ни одного из них (что приводило к «контексту»: []), хотя я не гарантирую, что это верно везде.
Я также могу игнорировать любые объекты в массиве с идентификатором, который меня не волнует (в данном случае v2Score и Threat_sources). Я включил их в пример, чтобы продемонстрировать, что могут быть данные, выходящие за рамки того, что мне нужно, и которые следует игнорировать. Кроме того, поля «имя» и «тип» в каждом из объектов можно игнорировать, поскольку для определения типа перечисления необходим только идентификатор и только «значение»< /code> необходим для выбора перечисления этого типа.
Я добрался до этого, прежде чем застрял в том, что делать. Я делаю все возможное, чтобы не использовать операторы switch для полей id или value, так как дополнения в будущем могут привести к ошибкам.

Код: Выделить всё

@JsonCreator
Context(
@JsonProperty("age") Age age,
@JsonProperty("Maturity") Maturity maturity,
@JsonProperty("coverage") Coverage coverage,
@JsonProperty("threat_intensity") ThreatIntensity intensity,
@JsonProperty("threat_recency") ThreatRecency recency,
) {
// basic constructor
}
Для приведенных выше входных данных необходимо создать следующий объект:

Код: Выделить всё

context.getAge() // Age.MORE_THAN_TWO_YEARS
context.getMaturity() // Maturity.HIGH
context.getCoverage() // Coverage.LOW
context.getThreatIntensity() // ThreatIntensity.VERY_LOW
context.getThreatRecency() // ThreatRecency.NONE
Не все элементы входного массива являются (логическими) перечислениями, но все элементы, которые меня интересуют, являются перечислениями.
Я Я предполагаю, что мне нужно каким-то образом использовать @JsonTypeInfo для каждого аргумента конструктора? Насколько я знаю, как это работает, если бы я мог аннотировать Enum вот так, отдельные перечисления были бы правильно десериализованы. Однако я не уверен, как преобразовать массив в отдельные параметры.

Код: Выделить всё

@JsonTypeInfo(
use = JsonTypeInfo.Id.CUSTOM,
as = JsonTypeInfo.As.EXTERNAL_PROPERTY,
property = "id",
defaultImpl = Void.class,
visible = false)
@JsonSubTypes({
@Type(value=Age.class, name="age"),
@Type(value=Maturity.class, name="maturity")
@Type(value=Coverage.class, name="coverage")
@Type(value=ThreatIntensity.class, name="threat_intensity")
@Type(value=ThreatRecency.class, name="threat_recency")})
public abstract class Enum implements Comparable, Serializable {

// annotating the implicitly-declared valueOf(String) method for Enums
@JsonCreator(mode = JsonCreator.Mode.PROPERTIES)
@JsonIgnoreProperties(ignoreUnknown = true)
public static abstract  T valueOf(@JsonProperty("value") String name);
}
Я также знаю, как создать для этого собственный десериализатор, но это делает код гораздо более хрупким, особенно если он будет расширен или изменен в будущем.


Подробнее здесь: https://stackoverflow.com/questions/786 ... n-property
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «JAVA»