Анализ действительно сложного вложенного json, структура которого постоянно меняется в JAVA

#java #json #parsing

#java #json #Разбор

Вопрос:

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

Вариант 1 — Самым простым способом сделать это было бы преобразовать / разобрать json в объект JAVA. Я перепробовал все (gson, JSONObject, Jackson …) Но я не могу преобразовать json, если у меня нет готового класса Java, а поскольку json не соответствует фиксированной структуре, я не могу преобразовать его в класс JAVA. Существует ли какая-либо другая библиотека, которая может преобразовать json в объект Java? (Без необходимости в ранее существовавшем классе java для преобразования json в)

Вариант 2 — Или есть ли способ / библиотека, которые я могу использовать, при котором, если задана часть json, программа печатает все элементы в файле json. Что-то вроде этого…

 StreetAddressLine
PrimaryTownName : value
CountryISOAlpha2Code :value
TerritoryAbbreviatedName :value
PostalCode : value

{"PrimaryAddress": [        {
          "StreetAddressLine": [{"LineText": "492 Koller St"}],
          "PrimaryTownName": "San Francisco",
          "CountryISOAlpha2Code": "US",
          "TerritoryAbbreviatedName": "CA",
          "PostalCode": "94110",
          "AddressUsageTenureDetail": [{"TenureTypeText":           {
            "@DNBCodeValue": 1129,
            "$": "Rents"
          }}],
          "PremisesUsageDetail": [{"PremisesUsageFunctionDetail": [{"PremisesFunctionText":           {
            "@DNBCodeValue": 12058,
            "$": "Manufacturing"
          }}]}],
          "CountyOfficialName": "San Francisco County",
          "TerritoryOfficialName": "California",
          "CountryGroupName": "North America",
          "GeographicalPrecisionText":           {
            "@DNBCodeValue": 0,
            "$": "Unknown"
          },
          "UndeliverableIndicator": false,
          "MetropolitanStatisticalAreaUSCensusCode": ["San Francisco-Oakland-Hayward CA"],
          "RegisteredAddressIndicator": false,
          "ResidentialAddressIndicator": false
        }]}
  

Большое спасибо!

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

1. Если структура постоянно меняется, класс был бы неподходящим. Даже если вы нашли библиотеку для генерации класса для вас во время выполнения, вы бы обращались к ней, не зная, существуют ли элементы. Если вы не можете исправить структуру JSON, тогда вам следует использовать динамическую структуру данных, подобную дереву.

2.на самом деле вы можете использовать gson для получения объекта Json, не зная класса, вместо этого используя метод parse JSONPARSER’а. Он возвращает общий файл JsonElement , который затем вы могли бы повторить, чтобы получить поля, которые вы хотите, чтобы делать то, что вы хотите.

3. @clearlyspam23 проблема с этим подходом заключается в том, что я не знаю полей, которые возвращаются в json, а без знания полей я не могу извлечь их из JsonElement

4. @Rohit если вы знаете, что возвращаемый json является типом объекта, вы можете вызвать метод JsonElement ‘s getAsJsonObject , чтобы получить JSONObject , затем, учитывая этот объект, выполнить итерацию по его значениям, используя EntrySet возвращенный from entrySet . Это должно позволить вам получить доступ к полному Json без необходимости знать какие-либо поля. Что вы будете делать с этими значениями, зависит от вас.

5. @clearlyspam23 звучит многообещающе, я проверю это, спасибо!

Ответ №1:

Попробуйте использовать json-simple для разбиения JSON на множество вложенных элементов JSONObject (которые в основном являются maps) и JSONArray (которые в основном являются списками) и извлеките значения самостоятельно.

Просто node: PrimaryAddress указывает, что также может существовать SecondaryAddress , поэтому вложенность не должна меняться, иначе может быть трудно определить, например, какому адресу StreetAddressLine принадлежит.

В таком случае лучшим вопросом было бы: почему структура меняется так часто?

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

1. Json — это ответ от веб-сервиса, созданного какой-то компанией. Структура меняется в зависимости от доступной информации. Спасибо за ваше предложение, я проверю его…

Ответ №2:

Хорошо, я нашел решение! Я использовал синтаксический анализатор Jackson

Сначала сопоставьте вашу jsonString с JsonNode

 JsonNode rootNode = mapper.readValue(jsonString, JsonNode.class);
  

Обновите корневой узел, чтобы он содержал json для требуемого ключа:

     rootNode = rootNode.findParent(key);
  

а затем, в зависимости от того, является ли это массивом или списком, обрабатывайте его отдельно:

 if(rootNode.path(key).isArray()){
//key is the field in the json that you might be looking for
for (final JsonNode objNode : rootNode) {

     for (Iterator<String> keyArray = objNode.getFieldNames(); keyArray.hasNext();){

         fieldName = keyArray.next();

         fieldValue = objNode.path(fieldName).asText();                 
         if(fieldValue != ""){
             System.out.println(fieldName   " = "   fieldValue);

         }else{
             arrayHandler(objNode,fieldName);
         }
     }
 }
  

На каждой итерации проверяйте, является ли результирующий JsonNode массивом или списком.
Если это список, обработайте его по-другому (просто выполните итерацию по парам ключ-значение, подобным этому)

 for (Iterator<String> keyArray = rootNode.getFieldNames(); keyArray.hasNext();){
        fieldName = keyArray.next();
        fieldValue = rootNode.get(fieldName).asText();
        System.out.println(fieldName   " = "   fieldValue);
    }
  

После каждой итерации проверяйте, каков следующий JsonNode, и рекурсивно вызывайте соответствующий обработчик…