#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. Я считаю, что это решает мою проблему. Большое вам спасибо.