t.me/atinfo_chat Telegram группа по автоматизации тестирования

Преобразование строки в JSON -> в объект

rest-assured
jsonpath
json
java
Теги: #<Tag:0x00007f21e3399188> #<Tag:0x00007f21e3398fa8> #<Tag:0x00007f21e3398e68> #<Tag:0x00007f21e3398d00>

(Kosmos) #1

Привет, всем.
Возможно, тема уже подымалась.

Я попытался протестировать API, который отдаёт ответ JSON с Content-Type: text/html; charset=UTF-8. В коде пытался преобразовать ответ в объект путём:

MyModel model = response.as(MyModel.class);

У меня появилась ошибка:

java.lang.IllegalStateException: Cannot parse object because no supported Content-Type was specified in response. Content-Type was 'text/html; charset=UTF-8'.

Решил преобразовывать в объект другим путём:

String s = response.asString();
JsonPath jsonPath = JsonPath.from(s);
MyModel testMyModel = jsonPath.getObject("$", MyModel.class);

но получил следующую ошибку:

java.lang.IllegalStateException: Cannot deserialize object because no JSON deserializer found in classpath. Please put either Jackson (Databind) or Gson in the classpath.

Для решения этой проблемы воспользовался добавлением в pom.xml библиотеки:

        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.9.5</version>
        </dependency>

но и тут поджидала очередная ошибка:

java.lang.NoClassDefFoundError: com/fasterxml/jackson/annotation/JsonMerge

Чтобы её пофиксить, нужно понизить версию библитеки jackson-databind до 2.8.x (https://www.mkyong.com/gradle/java-lang-noclassdeffounderror-comfasterxmljacksonannotationjsonmerge/). Попробовав у меня всё равно воспроизвелась та же ошибка. Тогда понизил версию библиотеки до 2.7.9.5, перезапустил и всё заработало!

Надеюсь, кому-нибудь будет полезно.


(Сергей Кузьмин) #2

response.body() десериализуйте

и snakeyaml лучше чем jackson (YMMV - мнение мое личное)

то есть я имел в виду скорее
com.alibaba.fastjson
и org.json.json


(Kosmos) #4

Попробовал

MyModel testMyModel = response.body().as(MyModel.class);

и получил ошибку:

java.lang.IllegalStateException: Cannot parse object because no supported Content-Type was specified in response. Content-Type was 'text/html; charset=UTF-8'.

(Сергей Кузьмин) #5

@blink2004 более древние и менее мажорные интсрументы чем джексон рекоммендуют less strong-typed approach:

        JSONObject obj = new JSONObject(json);
        String  bar = obj.getJSONObject("{foo:bar}").getString("foo");

ну и т.д.


(Kosmos) #6

OK. Тогда это уже другие библиотеки и другая история :slight_smile:


(Сергей Кузьмин) #7

@blink2004 вы сов правы но восток ^W лоу левел форматы штука тонкая и это помоему оправдывает выбор интсрумента - я по крайне й мере один случай знаю где jackson не могет… и что - писать в oss jiira у меня времени не хватает -


(Raynor) #8

Самый простой вариант - Gson

Gson gson = new Gson();
MyModel model = gson.fromJson(json, MyModel.class);

Где json - JSON строка

Здесь можно наити примеры JSON to object и JSON to array/list
https://www.lenar.io/how-to-convert-json-to-java-object-with-gson/
https://www.lenar.io/json-to-array-list-gson-java/

Кроме того, я лично если проект позволяет (и чаще всего так и есть) сразу работаю с requests/responses как с обьектами. RESTEasy proxy framework - супер удобно. Если того требует проект всегда можно опуститься на “HTTP” уровень и работать непосредсвенно с headers/response code/body

Здесь масса примеров
https://www.lenar.io/tags/resteasy/

Правда на английском


(Михаил Братухин) #9

Если в классе будет поле типа Map<String, Serializable> params, то может и не распарсится :slightly_smiling_face:


(Raynor) #10

О да, в любом варианте есть куча кейсов когда нужно исполнить ритуальный танец с бубном :grinning: