Я хочу извлечь определенные значения из пути массивов и объектов JSON и использовать эти значения для дальнейшей обработки, и я изо всех сил пытаюсь получить доступ к этим элементам. Вот ответ JSON:
[
{
"od_pair":"7015400:8727100",
"buckets":[
{
"bucket":"C00",
"original":2,
"available":2
},
{
"bucket":"A01",
"original":76,
"available":0
},
{
"bucket":"B01",
"original":672,
"available":480
}
]
},
{
"od_pair":"7015400:8814001",
"buckets":[
{
"bucket":"C00",
"original":2,
"available":2
},
{
"bucket":"A01",
"original":40,
"available":40
},
{
"bucket":"B01",
"original":672,
"available":672
},
{
"bucket":"B03",
"original":632,
"available":632
},
{
"bucket":"B05",
"original":558,
"available":558
}
]
}
]
Я попытался получить доступ к корневым элементам с помощью $, но не смог продвинуться дальше.
Вот метод тестирования, который я написал. Я хочу извлечь значение для od_pair, и в каждой od_pair мне нужно получить коды сегментов и их доступные номера.
public static void updateBuckets(String ServiceName, String DateOfJourney) throws Exception {
File jsonExample = new File(System.getProperty("user.dir"), "\\LogAvResponse\\LogAvResponse.json");
JsonPath jsonPath = new JsonPath(jsonExample);
List<Object> LegList = jsonPath.getList("$");
// List<HashMap<String, String>> jsonObjectsInArray = jsonPath.getList("$");
int NoofLegs = LegList.size();
System.out.println("No of legs :" + NoofLegs);
for (int j = 0; j <= NoofLegs; j++)
// for (HashMap<String, String> jsonObject : jsonObjectsInArray) {
{
String OD_Pair = jsonPath.param("j", j).getString("[j].od_pair");
// String OD_Pair = jsonObject.get("od_pair");
System.out.println("OD Pair: " + OD_Pair);
List<Object> BucketsList = jsonPath.param("j", j).getList("[j].buckets");
int NoOfBuckets = BucketsList.size();
// System.out.println("OD Pair: " + OD_Pair);
System.out.println("no of Buckets: " + NoOfBuckets);
for (int i = 0; i < NoOfBuckets; i++) {
String BucketCode = jsonPath.param("j", j).param("i", i).getString("[j].buckets[i].bucket");
String Available = jsonPath.param("j", j).param("i", i).getString("[j].buckets[i].available");
int BucketCodeColumn = XLUtils.getBucketCodeColumn(BucketCode);
int ServiceRow = XLUtils.getServiceRow(ServiceName, DateOfJourney, OD_Pair);
System.out.println("Row of " + ServiceName + ":" + DateOfJourney + "is:" + ServiceRow);
System.out.println("Bucket Code column of " + BucketCode + " is: " + BucketCodeColumn);
XLUtils.updateAvailability(ServiceRow, BucketCodeColumn, Available);
}
}
}
}
Это ошибка, которую я вижу:
Caused by:
org.codehaus.groovy.control.MultipleCompilationErrorsException: startup
failed:
Script1.groovy: 1: unexpected token: [ @ line 1, column 27.
restAssuredJsonRootObject.[j].od_pair
Может кто-то мне помочь, пожалуйста?
Я хочу иметь доступ не только к od_pair, но и к объектам ведра внутри. Таким образом, каждая od_pair имеет множество сегментов в качестве объектов. С вашим решением Hashmap я не уверен, как я могу связаться с различными сегментами в каждой od_pairs
Да, это правильно @Fenio
Хорошо, понял. Есть несколько решений, но я покажу вам расширенное и лучшее (на мой взгляд). мне нужно несколько минут
@Fenio: Итак, в основном я пытаюсь запустить вложенные циклы for, один для получения od_pair, а внутри него цикл for для сегментов, чтобы получить код каждого сегмента и доступный номер. Извините, поскольку я новичок, и поэтому некоторые из моих вопросов могут показаться здесь наивными.
Не извиняйтесь за вопросы. Просто убедитесь, что люди понимают, что вы хотите сделать, и приложите усилия :)
Я бы предложил разобрать ваш JSON на классы Java, чтобы облегчить обработку.
Как это сделать? Во-первых, нам нужно создать классы Java, которые будут представлять предоставленный вами JSON.
Давайте проанализируем JSON.
Начинается с массива. Массив содержит несколько объектов JSON. Эти объекты содержат значение od_pair
и массив объектов с именем buckets
.
Давайте создадим класс (вы можете назвать его как хотите) Pair
public class Pair {
public String od_pair; //this name is important because it corresponds with the json element's name!
public List<BucketObject> buckets; //same here!
}
Этот класс представляет один объект JSON в основном массиве. Он содержит od_pair
значение И вложенный массив JSON, но в представлении Java -> Список BucketObject
классов. Давайте создадим класс BucketObject
:
public class BucketObject { //this name is NOT importnat
public String bucket; //names are important
public int original;
public int available;
}
У нас есть только 3 значения в каждом из объектов.
Теперь пришло время разобрать JSON на письменные классы.
JsonPath path = JsonPath.from(json);
Pair[] pairs = path.getObject("$", Pair[].class);
Помните, что Pair
— это один объект JSON. Вот почему мы начинаем синтаксический анализ с корня, представленного знаком доллара $
, и объявляем, что JSON следует анализировать в МАССИВ Pair
объектов!
Теперь обработка будет намного проще!
Я не уверен, что вам нужно, но я покажу вам пример того, как получить данные из корзин на основе поля od_pair
, и вы сможете понять остальную часть обработки.
Итак, у нас есть массив класса Pair: Pair[] pairs
;
Теперь мы хотим получить 1 объект Pair на основе значения od_pair
.
public static Pair getPairBasedOnOdPairValue(Pair[] pairs, String odPairValue) {
for (Pair pair : pairs) {
if (pair.od_pair.equals(odPairValue)) return pair;
}
throw new NoSuchElementException();
}
Теперь у нас есть объект Pair
. Мы можем получить доступ к buckets
для этого объекта, используя
List<BucketObject> buckets = pair.buckets;
Остальная часть обработки — это повторение List<BucketObject>
и получение желаемых значений.
Надеюсь, поможет!
Большое спасибо @Fenio, я реализую этот подход и сообщу, как он идет.
@Mihir Если у вас больше проблем - создайте еще один вопрос. Я регулярно просматриваю вопросы с пометкой rest assured
:)
Хорошо, обязательно сделаю @Fenio. Большое тебе спасибо
Большое спасибо за ваше решение. просто для моего понимания и обучения, не могли бы вы также посоветовать код цикла for, который я написал ранее. Где я вложил один цикл for для получения od_pair и один для получения информации о сегменте, пожалуйста? Что я там упустил или где я ошибся? @Фенио
@Mihir завтра проверю
@Mihir Я добавил некоторые пояснения во второй ответ. Я не могу просто указать, где вы ошиблись, но, надеюсь, вы сможете исправить это самостоятельно.
Создал новый вопрос по этому поводу в - stackoverflow.com/questions/57288085/… @Fenio
Мне удалось решить проблему в stackoverflow.com/questions/57288085/…. Я тоже добавил решение. Спасибо за вашу помощь :) @Fenio
ОП попросил меня посоветовать, как исправить его код, отсюда и второй ответ.
Давайте проанализируем код, который вы предоставили:
public static void updateBuckets(String ServiceName, String DateOfJourney) throws Exception {
File jsonExample = new File(System.getProperty("user.dir"), "\\LogAvResponse\\LogAvResponse.json");
JsonPath jsonPath = new JsonPath(jsonExample);
List<Object> LegList = jsonPath.getList("$");
// List<HashMap<String, String>> jsonObjectsInArray = jsonPath.getList("$");
int NoofLegs = LegList.size();
System.out.println("No of legs :" + NoofLegs);
for (int j = 0; j <= NoofLegs; j++)
// for (HashMap<String, String> jsonObject : jsonObjectsInArray) {
{
String OD_Pair = jsonPath.param("j", j).getString("[j].od_pair");
// String OD_Pair = jsonObject.get("od_pair");
System.out.println("OD Pair: " + OD_Pair);
List<Object> BucketsList = jsonPath.param("j", j).getList("[j].buckets");
int NoOfBuckets = BucketsList.size();
// System.out.println("OD Pair: " + OD_Pair);
System.out.println("no of Buckets: " + NoOfBuckets);
for (int i = 0; i < NoOfBuckets; i++) {
String BucketCode = jsonPath.param("j", j).param("i", i).getString("[j].buckets[i].bucket");
String Available = jsonPath.param("j", j).param("i", i).getString("[j].buckets[i].available");
int BucketCodeColumn = XLUtils.getBucketCodeColumn(BucketCode);
int ServiceRow = XLUtils.getServiceRow(ServiceName, DateOfJourney, OD_Pair);
System.out.println("Row of " + ServiceName + ":" + DateOfJourney + "is:" + ServiceRow);
System.out.println("Bucket Code column of " + BucketCode + " is: " + BucketCodeColumn);
XLUtils.updateAvailability(ServiceRow, BucketCodeColumn, Available);
}
}
}
Сейчас я не использую компилятор, поэтому могу кое-что упустить.
#1
Первое, что я вижу, это то, что вы сохраняете основной массив в List<Object>
List<Object> LegList = jsonPath.getList("$");
Вместо этого вы можете сохранить его в более понятном виде, поскольку Object настолько универсален, что вы понятия не имеете, что у него внутри.
List<HashMap<String, Object>> LegList = jsonPath.getList("$");
#2
Цикл for
выглядит неправильно из-за оценщика
j <= NoofLegs;
.
Это, вероятно, вызовет IndexArrayOutOfBoundsException
или что-то подобное. С данным кодом, если у вас есть 4 ноги, цикл for
попытается обработать 5 ног, которые неверны.
#3
Аналогично строке № 1, в которой вы сохраняете список сегментов.
List<Object> BucketsList = jsonPath.param("j", j).getList("[j].buckets");
Вместо этого также можно изменить на List<HashMap<String, Object>>
.
Если бы вы сделали это, вам не понадобился бы вложенный цикл for
на основе целых чисел.
Видите ли, HashMap<String, Object>
на самом деле имеет решающее значение для разбора вложенных объектов. Строка — это просто имя, например buckets
или od_pair
. Это представление JSON. Второй аргумент Object
отличается. RestAssured возвращает разные типы в HashMap, поэтому мы используем Object
вместо String
. Иногда это не String.
Пример на основе вашего JSON:
Соберите ведра в список HashMaps:
List<HashMap<String, Object>> bucketsList = jsonPath.param("j", j).getList("[j].buckets");
Каждый из HashMap в списке является представлением этого:
{
"bucket":"C00",
"original":2,
"available":2
},
Object
в HashMap
в вашем случае либо String
, либо Integer
.
Итак, если вы получите элемент bucket
из HashMap
, вы получите его значение.
Давайте объединим это с циклом for
для дальнейшего уточнения:
List<HashMap<String, Object>> bucketsList = jsonPath.param("j", j).getList("[j].buckets");
for (HashMap<String, Object> singleBucket : bucketsList) {
String firstValue = (String) singleBucket.get("bucket");
Integer secondValue = (Integer) singleBucket.get("original");
}
Большое спасибо за объяснение. Ваше объяснение очень ясное и помогает понять это так хорошо. Большое спасибо за вашу помощь, сэр!
@Mihir Добро пожаловать :) Не стесняйтесь задавать дополнительные вопросы, если вам нужна помощь.
Мне понравился этот вышеприведенный подход, который вы предоставили. У меня только один вопрос по этому поводу. Я снова добавил раздел ниже. Пожалуйста, ответьте. @Fenio
Глядя на сообщение об ошибке, похоже, что вы используете Будьте уверены и что класс JsonPath
io.restassured.path.json.JsonPath
из надежной библиотеки.
Я уверен, что вы знаете, но (возможно, для других читателей) обратите внимание, что это отличается от json-путь Jayway и НЕ является классом com.jayway.jsonpath.JsonPath
из этой библиотеки.
Также имейте в виду, что, как упоминалось в документация rest-assured, используется синтаксис Groovy-GPath для манипулирования/извлечения JSON.
При этом я считаю, что следующее извлечет то, что вам нужно, то есть od_pair и соответствующие им сегменты с доступными номерами:
Map<String, Map<String, Integer>> map = JsonPath.with(jsonString).get("collectEntries{entry -> [entry.od_pair, entry.buckets.collectEntries{bucketEntry -> [bucketEntry.bucket, bucketEntry.available]}]}");
где для каждой записи карты ключ — это od_pair, а значение — это другая карта, ключом которой является ведро, а значением — доступный номер. jsonString
— это JSON, который вы указали в вопросе.
Вы можете перебирать карту, чтобы получить то, что хотите:
for(Map.Entry<String, Map<String, Integer>> entry : map.entrySet())
{
String od_pair = entry.getKey();
Map<String, Integer> bucketMap = entry.getValue();
for(Map.Entry<String, Integer> bucketEntry : bucketMap.entrySet())
{
String bucket = bucketEntry.getKey();
int available = bucketEntry.getValue();
}
}
Распечатав карту вы получите:
{7015400:8727100 = {C00=2, A01=0, B01=480}, 7015400:8814001 = {C00=2, A01=40, B01=672, B03=632, B05=558}}
Печать карты в формате JSON с использованием Gson:
System.out.println(new GsonBuilder().setPrettyPrinting().create().toJson(map));
ты получишь
{
"7015400:8727100": {
"C00": 2,
"A01": 0,
"B01": 480
},
"7015400:8814001": {
"C00": 2,
"A01": 40,
"B01": 672,
"B03": 632,
"B05": 558
}
}
Для фона строка collectEntries{entry -> [entry.od_pair, entry.buckets.collectEntries{bucketEntry -> [bucketEntry.bucket, bucketEntry.available]}]}
представляет собой замыкание Groovy, использующее методы из API коллекций Groovy: см. Коллекция, Список и карта.
Спасибо @Fenio за чистое Java-решение, описанное выше.
I need to be able to retrieve the bucket codes and their available numbers.
На основеod_pair
, верно?