2014-09-01 4 views
3

Добро пожаловать,Play 2.3 с Scala, преобразование JSON массива в последовательность

Я действительно хотел, чтобы избежать этого, но я отказаться сейчас. Я пытаюсь пройти через json-массив и вывести некоторые элементы и привести их в порядок. Я попробовал множество опций, попробовал все из игровых документов, много попыток и все еще имею ту же ошибку: исключение null-указателя, когда мой метод пытается удалить элементы. Так что мой JSON пример:

[ 
    { 
    "var1": "xx", 
    "var2": "xxx", 
    "var3": 111 
    }, 
    { 
    "var1": "yy", 
    "var2": "yyy", 
    "var3": 222 
    }, 
    { 
    "var1": "zz", 
    "var2": "zzz", 
    "var3": 333  
    } 
] 

я определил множество конфигураций читает, последний, как это, но не хочет компилировать даже;/

case class Vars1(vars: Seq[String]) 
val var1Reads: Reads[String] = (__ \ "var1").read[String] 
implicit val vars1Reads: Reads[Vars1] = ((__).read[Seq[String]])(Vars1.apply _) 

Я хочу создать последовательность или список, это не важно, только от var1 от каждого элемента этого массива. Это может быть чистая последовательность, или класс случая с последовательностью или другим. Просто, как итерации через json-массивы? Я пробовал много конфигураций, чтение var1 не является проблематичным, но когда я хочу прочитать все vars 1 из каждого элемента массива, тогда у меня есть исключение из null-указателя. Пожалуйста, любой может указать мне в хорошем направлении, дать мне подсказку, что я делаю неправильно? Пожалуйста, не вините, я новичок в программировании, и я начал изучать scala и play framework.

Благодарим за помощь.

Update:

Я попробовал этот тоже:

implicit val vars1Reads = (__).read(Reads.list((__).read[String])).map(var => Vars(var)) 

, но до сих пор я имею ту же ошибку:

[NoSuchElementException: JsError.get] 
+0

Объявите, что ваши чтения являются ленивыми, например, 'implicit lazy val vars1Reads'. Это раздражающий и совершенно запутанный источник НСЕ. – Ryan

ответ

3

Самый простой способ разбора это позволить Play разобрана тело массива как Seq[_], то есть последовательность объектов.

Я бы предположил, что каждый элемент в вашем массиве должен быть представлен классом case, например.

case class Var1(var1: String) 

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

Вы можете добавить неявный Reads в соответствующем месте, например.

object Var1 { 
    implicit val var1Reads: Reads[Var1] = { 
    ((__ \ "var1").read[String]).map(Var1.apply _) 
    } 
} 

Обратите внимание, что макросы чтения/записи имеют ограничение, когда они не работают в документированной образом, где класс случае имеет одно поле - см http://grokbase.com/t/gg/play-framework/131bx7pcyd/play2-1-scala-json-writing-a-reads-writes-for-a-single-field-case-class - Вот почему map вызов добавляется. Макрос должен работать как задокументированный, если имеется 2 или более полей.

Затем вы можете использовать это для создания Seq [Var1], например.

def test = Action(BodyParsers.parse.json) { request => 
    val result = request.body.validate[Seq[Var1]] 
    ... 
} 

И результат (здесь я просто распечатываю значение результата.ToString) является:

$ curl --include --request POST --header "Content-type: application/json" --data '[{"var1": "3", "var2": "4"}, {"var1": "7"}]' http://localhost:9000/test 
HTTP/1.1 200 OK 
Content-Type: text/plain; charset=utf-8 
Content-Length: 34 

JsSuccess(List(Var1(3), Var1(7)),) 

Update

Как уже упоминалось в комментариях ниже, вы можете упростить Reads[Var1] реализацию с помощью макроса так:

implicit val var1Reads = Json.reads[Var1] 

Это будет делать только то, что вы если поле называется var1, то есть

case class Var1(var1: String) 
+0

Ограничение на однополевые классы случаев было исправлено в версии 2.1-RC2 в соответствии с [docs] (https://www.playframework.com/documentation/2.3.x/ScalaJsonInception). –

+0

Это действительно так. Однако, '((__ \" var1 "). Read [String]) (Var1.apply _)' приводит к ошибке компиляции 'Значение перегруженного метода [read] не может быть применено к (String => controllerlersVar1)', в то время как тот же шаблон, примененный к нескольким полям, работает (с Play 2.3.4). Мое предположение заключается в том, что не все ситуации были исправлены, но необходимы дополнительные исследования. –

+0

Ах, я думаю, что исправленная вещь была макросъемкой, например. 'implicit val var1Reads = Json.reads [Var1]'. Я могу подтвердить, что он работает. Я обнаружил, что генерация макросов достаточно надежна, что мне не нужно писать самостоятельно. –

Смежные вопросы