Джексон десериализует JSON в pojo с помощью свойства карты

#java #jackson

Вопрос:

Кто-нибудь может мне помочь, как я могу десериализовать следующий JSON, который я не могу изменить? Я использую Джексона для сериализации.

 {      
    "columns": [
      {
        "header": "Heading1",
      },
      {
        "header": "Heading2",
      }
    ],
    "rows": [
       "id": 1,
       "Heading1": {
          "value": "Value1"
       },
       "Heading2": {
          "value": "Value2"
       }
    ]
}
 

Столбцы могут иметь неизвестное количество заголовков и их значение, например. «Header1» используется в массиве строк.

До сих пор у меня есть следующая структура:

 public class QueryResult {
   private ColumnConfig[] columns;
   private QueryResultRow[] rows;
}
public class ColumnConfig {
   private String header;
}
public class QueryResultRow {
   private int id;
   private Map<String, CellValue> values;
}
public class CellValue{
   private String value;
}
 

Проблема в том, что карта пуста, когда я десериализуюсь в QueryResu<
Я читал о типе,но я не знаю,как я могу указать тип<HashMap<Строка, значение ячейки><Строка, значение ячейки>> для значений свойств в QueryResultRow.

Редактировать:

Мой код сопоставления объектов выглядит следующим образом:

 ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
String queryResultString = loadQuery(queryPath);
        QueryResult result = mapper.readValue(queryResultString, QueryResult.class);
 

Содержимое строки QueryResult-это JSON, указанный выше.

Комментарии:

1. JSON десериализация кода может быть полезна для всех.

2. Покажите нам свой ObjectMapper код десериализации.

3. Воспользуйся @JsonAnySetter .

Ответ №1:

Первая проблема заключается в том, что ваш JSON недействителен. Я предполагаю, что это должно быть что-то вроде этого,

 {
  "columns": [
    {
      "header": "Heading1"
    },
    {
      "header": "Heading2"
    }
  ],
  "rows": [
    {
      "id": 1,
      "Heading1": {
        "value": "Value1"
      },
      "Heading2": {
        "value": "Value2"
      }
    }
  ]
}
 

Тогда ответ довольно прост. Вам необходимо изменить свой QueryResultRow следующим образом,

 class QueryResultRow {
    private int id;
    private Map<String, CellValue> values = new HashMap<>();
    
    @JsonAnySetter
    public void addValues(String k, CellValue v) {
        values.put(k, v);
    }
}
 

Тогда, я думаю, тебе пора идти.

Вот полный рабочий пример,

 public class Main {
    public static void main(String[] args) throws IOException {
        String s = "{"columns":[{"header":"Heading1"},{"header":"Heading2"}],"rows":[{"id":1,"Heading1":{"value":"Value1"},"Heading2":{"value":"Value2"}}]}";
        
        ObjectMapper om = new ObjectMapper();
        QueryResult queryResult = om.readValue(s, QueryResult.class);

        System.out.println(queryResult);
    }
}

@Getter
@Setter
@ToString
class QueryResult {
    private ColumnConfig[] columns;
    private QueryResultRow[] rows;
}

@Getter
@Setter
@ToString
class ColumnConfig {
    private String header;
}

@Getter
@Setter
@ToString
class QueryResultRow {
    private int id;
    private Map<String, CellValue> values = new HashMap<>();
    
    @JsonAnySetter
    public void addValues(String k, CellValue v) {
        values.put(k, v);
    }
}

@Getter
@Setter
@ToString
class CellValue{
    private String value;
}