2

Я пытаюсь использовать вещи читателя/комбинатора для анализа массива, который содержит смешанные типы данных, но я не уверен, как указать читателя для такой вещи. У меня есть некоторые JSON как это:PlayFramework 2.2 - Scala - Read Mixed Arrays

{ 
    "stuff": [1, 2, true, null, "false", "hahaha", 5, "8"] 
} 

Я хочу, чтобы разобрать все это в строку-представление, но когда я просто пытаюсь использовать кард из List[String] я разобрать исключения. Я полагаю, что-то вроде этого:

implicit val mixedArrayReader = (
     (__ \ 'not).readNullable[List[JsValueWrapper]].map(opt => opt.map(list => 
      list.map { wrapper : JsValueWrapper => 
       val parsed : String = wrapper match { 
         case b : JsBoolean => if (b.value) "1" else "0" 
         case n : JsNumber => n.value.toString 
         case s : JsString => s.value 
         case JsNull  => "null" 
         case u    => u.toString // unknown 
        } 
       parsed 
       } 
     )) 
) 

Однако, так как нет читалки для JsValueWrapper, я не уверен, куда идти отсюда. Любая помощь приветствуется.

Спасибо!

ответ

3

Начните с реализации индивидуального чтения [String], затем используйте Reads.list, чтобы превратить его в считывающее устройство List[String], а затем используйте его как обычно. Предпочитают пропускать этих конкретных читателей явно против определения имплицитов для них, чтобы не скрывать значение по умолчанию Reads[String].

import play.api.libs.json.Reads 

val myReader: Reads[String] = Reads[String](value => JsSuccess(value match { 
    case b : JsBoolean => if (b.value) "1" else "0" 
    case n : JsNumber => n.value.toString 
    case s : JsString => s.value 
    case JsNull  => "null" 
    case u    => u.toString // unknown 
})) 

val listReads = Reads.list[String](myReader) 

Затем, в сочетании читателя вы можете написать что-то вроде:

implicit val objReader = 
    (__ \ 'not).readNullable(listReads) 
1

Решение по thesamet является, вероятно, наиболее прямо вперед. Я думаю, что ваше решение будет работать, если вы используете .readNullable[List[JsValue]], JsValue - это супер тип всех типов Js *, оболочка, с которой вам никогда не придется работать напрямую, она существует только для облегчения создания объектов JSON и массивов.

Еще более функциональным и гибким решением (обратите внимание, что это решение обрабатывает ошибки гораздо лучше), что вы могли бы использовать это:

val anyValueAsStringReader = 
    implicitly[Reads[BigDecimal]].map(_.toString) or 
    implicitly[Reads[String]] or 
    implicitly[Reads[Boolean]].map(if (_) "1" else "0") or 
    implicitly[Reads[JsValue]].map(_.toString) 

val mixedArrayReader = (__ \ 'not).readNullable(Reads.list(anyValueAsStringReader)) 
Смежные вопросы