Сопоставление значений объектов с учетом нескольких строк

#java #jackson

#Ява #джексон

Вопрос:

Я получаю следующий json от внешнего вызова rest.

 {  // other keys coming in too, but already mapped  "someData": {  "someContent": {  "item1": "",  "otherItem25": "",  "anotherData34": ""  }  } }  

Я хочу сопоставить его с объектом.

Я мог бы сделать следующее, что работает.

Решение 1

 private Maplt;String, Maplt;String, Stringgt;gt; someData;  

Но я хочу сопоставить его с именованными объектами.

Например, следовать, что тоже работает.

Решение 2

 class Root {  private someData someData; }  class SomeData {  private SomeContent someContent; }  class SomeContent {  @JsonProperty("item1")  private String one;   @JsonProperty("otherItem25")  private String two;   @JsonProperty("anotherData34")  private String three; }  

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

Помимо вышеперечисленных 2 решений, есть ли лучший способ сопоставить этот json с объектом?

Что-то подобное было бы идеальным, но не сработает, потому что нет ничего, что можно было бы идентифицировать как nnerData в json.

 class SomeContent {  private Maplt;String, Stringgt; innerData; }  

Пожалуйста, посоветуйтесь.

P. S: Я не могу изменить json

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

1. Ты используешь Джексона?

2. @JeffScottBrown Да, используя Джексона. Это находится внутри приложения spring boot.

3. Я добавил jackson тег для уточнения.

4. @JeffScottBrown Спасибо. Отсутствие ответов, похоже, приводит к предположениям, что лучшего способа нет.

Ответ №1:

Похоже, что «идеальный случай» может быть реализован с @JsonCreator аннотацией и передачей карты с «внутренними данными» в конструктор.

 class TestJson {   @Test  void test() throws Exception {   var json = "{"    " "someData": {"    " "someContent": {"    " "item1": "hello","    " "otherItem25": "245hb24bt","    " "anotherData34": "b42tb245""    "}}}";   var value = new ObjectMapper().readValue(json, Root.class);   assertThat(value.someData.someContent.innerData.get("item1"))  .isEqualTo("hello");  }    // here we use "public" just to make the code shorter  // and let Jackson bind properties to the public fields    static class Root {   public SomeData someData;  }   static class SomeData {   public SomeContent someContent;  }   static class SomeContent {   public final Maplt;String, Objectgt; innerData;   @JsonCreator  public SomeContent(Maplt;String, Objectgt; anyName) {  this.innerData = Map.copyOf(anyName);  // notice that the map "anyName" is mutable  }  } }  

Пожалуйста, дважды проверьте, нет ли здесь чрезмерной инженерии, и это именно то, что требуется в решении. Вероятно, было бы достаточно просто Map ввести поле «someContent» (а также рассмотреть возможность обработки изменчивости карты в этом случае).

 class SomeData {  Maplt;String, Stringgt; someContent; }  

Ответ №2:

Если я правильно читаю вопрос, похоже, что вы хотите отобразить большую часть объекта в виде Java-компонентов, но хотите someContent отобразить его как a Map . Предполагая, что это так, вы можете сопоставить различные свойства, не относящиеся к компонентам, как обычно, а затем отобразить someContent как a Maplt;String, Stringgt; во внутреннем SomeData типе.

 class Root {  private SomeData someData; }  class SomeData {  private Maplt;String, Stringgt; someContent; }  

Ответ №3:

карта будет лучшим вариантом, на мой взгляд, если ваш json будет динамичным и будет очень часто меняться. если вас интересуют только определенные свойства из любой случайной вещи , которая может быть добавлена в ответ, тогда просто сопоставьте свойства, которые вам нужны, в POJO и используйте аннотацию @JsonIgnoreProperty(игнорировать=неизвестно), чтобы игнорировать дополнительные вещи, которые придут в ответ, которые вас даже не интересуют.