обновление объекта Json

#json #scala #playframework-2.0

#json #scala #playframework-2.0

Вопрос:

У меня есть объект json, который мне нужно обновить. Исходный объект представляет собой список, который выглядит следующим образом:

 [
  {
    "firstName":"Jane",
    "lastName":"Smith"
  },
  {
    "firstName":"Jack",
    "lastName":"Brown"
  }
]
 

Для каждого элемента в списке у нас есть дополнительное поле «возраст», которое необходимо добавить во время выполнения, поэтому результат должен выглядеть следующим образом:

 [
  {
    "firstName":"Jane",
    "lastName":"Smith",
    "age": "21"
  },
  {
    "firstName":"Jack",
    "lastName":"Brown",
    "age": "34"
  }
]
 

Любые предложения, как это сделать, чтобы результат по-прежнему оставался json?

Спасибо.

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

1. Как вы должны определить, какой возраст добавить к какому объекту?

2. @LimbSoup Я получу их во время выполнения. Пример намеренно упрощен. Все, что мне нужно знать, это как де-сконструировать исходный Json и повторно сконструировать его снова с дополнительным полем.

Ответ №1:

 request.body.asJson.map {
  jm => (jm.as[JsObject]    Json.obj("age" -> 123))
}
 

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

1. Мое значение json исходит из ответа, а не из запроса. Response.body.asJson или response.json.map, конечно, не компилируются…

2. Что / где является источником JSON? Является ли это результатом вызова webservice ( play.api.libs.ws.WS ) Или удаления из других объектов и т. Д.?

3. @user3777482: откуда бы ни появлялся ваш json, это никак не влияет на то, как вы обновляете json. Для обновления json это то, что вам нужно (jm.as[JsObject] Json.obj("age" -> 123)) , как описано в моем ответе

4. @Vikas Pandya — Мой Json является значением JsValue, но не JSObject, поэтому код выдает ошибку во время выполнения.

5. @Donovan Muller — Да, мой код является результатом вызова веб-сервиса.

Ответ №2:

Я бы рекомендовал десериализовать полученный массив JSON в несколько List классов case, затем использовать некоторую функцию, заполняющую недостающие атрибуты на основе текущих атрибутов класса case, и, наконец, сериализовать их как JSON и отправить ответ.

Давайте создадим Person класс case с полями, которые будут отсутствовать как Option :

 import play.api.libs.json.Json

case class Person(firstName: String, lastName: String, age: Option[Int])

object Person {
    implicit val format: Format[Person] = Json.format[Person]

    def addAge(person: Person): Person = {
        val age = ... // however you determine the age
        person.copy(age = Some(age))
    }
}
 

В сопутствующем объекте for Person я также определил сериализатор / десериализатор JSON с помощью format макроса и заглушку для функции, которая найдет возраст человека, затем скопирует его обратно в person и вернет.

Глубоко внутри вызова веб-службы у вас может быть что-то вроде этого:

 val jsArray = ... // The JsValue from somewhere

jsArray.validate[List[Person]].fold(
    // Handle the case for invalid incoming JSON
    error => InternalServerError("Received invalid JSON response from remote service."),
    // Handle a deserialized array of List[Person]
    people => {
        Ok(
            // Serialize as JSON, requires the implicit `format` defined earlier.
            Json.toJson(
                // Map each Person to themselves, adding the age
                people.map(person => Person.addAge(person))
            )
        )
    }
)
 

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

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

1. Я считаю, что это решает мою проблему. Большое вам спасибо.