#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(игнорировать=неизвестно), чтобы игнорировать дополнительные вещи, которые придут в ответ, которые вас даже не интересуют.