Разбор ответа NoSQL с помощью Gson - PullRequest
1 голос
/ 24 сентября 2019

Я пытаюсь проанализировать объект JSON, возвращенный из экземпляра mongoDB, и у меня возникла проблема при разборе идентификаторов документов.Смотрите пример ответа ниже:

{  
    "type_id":"zyxwv54321",
    "content":{  
       "contentsA":{  
          "abcd123":{  },
          "efgh123":{  },
          "ijkl123":{  },
          "mnop123":{  },
          "qrst123":{  },
          "uvwx123":{  },
          "yzab123":{  }
       },
       "contentsB":{  
          "abcd123":{  },
          "efgh123":{  },
          "ijkl123":{  },
          "mnop123":{  },
          "qrst123":{  },
          "uvwx123":{  },
          "yzab123":{  }
       }
    },
    "manager":"mail@mail.com"
}

Проблема с объектами в contentsA и contentsB, как мне разобрать их?Каждая из строк, содержащихся в этих объектах, является уникальным идентификатором, который будет меняться, поэтому трудно найти класс модели данных, учитывая неизвестную природу этих ключей.

1 Ответ

0 голосов
/ 25 сентября 2019

Вам потребуется реализовать собственный настраиваемый сериализатор / десериализатор, который может анализировать JSON со значениями динамического ключа.Это не будет красиво, но не ужасно.И на самом деле обеспечивает несколько преимуществ с точки зрения производительности:

  1. Ваш JSON не анализируется все сразу, а вместо этого анализируется в потоковом режиме
  2. Вы можете делать интересные вещи с этим, так как выможет обернуть эти данные с помощью некоторого реактивного программирования и некоторого постоянного хранилища и начать немедленно отображать что-то для пользователя, когда вы анализируете JSON (потому что пользователи ненавидят ждать ...)

Использование GSON (но на самом деле любоебиблиотека будет похожа по своей концепции) вам нужно будет описать свой объект в алгоритме синтаксического анализа + реализовать пользовательский TypeAdapter , чтобы ваш сетевой вызов мог вернуть заполненный класс Data Model.Итак, что-то вроде этого:

val jsonReader = JsonReader(inputStream.reader())
jsonReader.isLenient = true //I recommend reading up on this flag
jsonReader.beginObject()
parseInternals(jsonReader)
jsonReader.endObject()

Теперь в вашей функции parseInternal вам нужно будет пройти через поля во время потоковой передачи ответа и проверить тип JsonToken (это перечисление)

fun parseInternals(jsonReader: JsonReader): YourDataModel {
 //check there are still tokens to parse in your JSON
 val yourDataModel = YourDataModel()
 while (jsonReader.hasNext()) { 
   //name is a key in your JSON
   if (jsonReader.peek() == JsonToken.NAME) { 
     val fieldName = jsonReader.readName()
     if (fieldName == "type_id") {
       dataModel.typeId = jsonReader.nextString()

     }
     //and so on until you populate your data model class
   }
 }
}

Ваш следующий токен будет content , который начинается как другой объект, так что вам нужно будет вручную делать jsonReader.begin/endObject(), пока вы не доберетесь до тех динамических клавиш, которые просто являются nextName в вашем парсере,Обязательно проверяйте тип следующего токена с помощью jsonReader.peek() и сравнивайте его с тем, что вы ожидаете увидеть там.

После написания парсера, напишите несколько тестов для него, чтобы убедиться, что он делает то, что от него ожидали.Это поможет с проверкой на будущее в случае, если схема JSON когда-либо изменится, чтобы вы могли поймать ее раньше.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...