Scala анализирует неканонический JSON

Следующие данные можно увидеть с различными типами значений. Как я могу получить желаемый результат?

package ceshi

import scala.util.parsing.json.JSON

object ceshi1212 {
  def main(args: Array[String]): Unit = {


    class CC[T] {
      def unapply(a: Any): Option[T] = Some(a.asInstanceOf[T])
    }

    object M extends CC[Map[String, Any]]
    object L extends CC[List[Any]]
    object S extends CC[String]

    val jsonString =
      """
      {
        "languages": [
        {
            "name": "English",
            "is_active": "true",
            "completeness": "asdf"
        },
        {
            "name": "Latin",
            "is_active": "asdf",
            "completeness": "232"
        }
            ,{
                "name": "Latin",
                "is_active": "0009"
            }
            ,
            "error"
                  ]
      }
    """.stripMargin
    // 不规则json error和并列的数组类型不同 怎么解析自动跳过?
    val result = for {
      Some(M(map)) <- List(JSON.parseFull(jsonString))
      L(languages) = map("languages")
      M(language) <- languages
      S(name) = language("name")
      S(active) = language("is_active")
      S(completeness) = language.getOrElse("completeness","--")
    } yield {
      (name, active, completeness)
    }

    println(result)
    //i want result is:  List((English,true,asdf), (Latin,asdf,232),(Latain,0009,""))

  }
}

я хочу получить результат в виде списка ((английский, true, asdf), (латинский, asdf, 232), (латинский, 0009, "")) примечание: 1 Строка не всегда находится в конце массива, а позиция не определена 2 Три необходимых мне ключа могут быть неполными

scala.until.parsing.json более чем устарел, лучше взгляните на современную/поддерживаемую библиотеку
cchantep 11.12.2020 10:07
Как сделать HTTP-запрос в Javascript?
Как сделать HTTP-запрос в Javascript?
В JavaScript вы можете сделать HTTP-запрос, используя объект XMLHttpRequest или более новый API fetch. Вот пример для обоих методов:
0
1
111
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Как сказано в комментариях, есть и другие библиотеки, которые можно порекомендовать для работы с json. Взгляните на этот пост, чтобы получить обзор: Какую библиотеку JSON использовать в Scala?

Ответьте на ваш вопрос с конкретным фреймворком (play-json)

Лично я могу порекомендовать использовать фреймворк play json. Чтобы получить описанный вами результат с помощью play json, ваш код может выглядеть так:

import play.api.libs.json._

val json: JsValue = Json.parse(jsonString)
val list = (json \ "languages").as[Seq[JsValue]]

val names = list.map(x => ((x\"name").validate[String] match {
  case JsSuccess(v, p ) => v
  case _ => ""
  }
))

val isActives = list.map(x => ((x\"is_active").validate[String] match {
  case JsSuccess(v, p ) => v
  case _ => ""
  }
))

val completeness = list.map(x => ((x\"completeness").validate[String] match {
  case JsSuccess(v, p ) => v
  case _ => ""
  }
))

// need to know in advance what is your max length of your tuple (tmax)
//  since 3rd value "completeness" can be missing, so we just take "" instead
val tmax = 3 
val res = for(idx <-0 to tmax-1) yield (names(idx),isActives(idx),completeness(idx))
res.toList
// List[(String, String, String)] = List((English,true,asdf), (Latin,asdf,232), (Latin,0009,""))

Также есть очень хорошая документация по фреймворку play json, просто посмотрите сами: https://www.playframework.com/documentation/2.8.x/ScalaJson

Обратите внимание, что сама спецификация JSON не видит разницы между "" и отсутствием значения. Программное обеспечение, которое ожидает, что значения "" будут представлены как текущее значение "", всегда будет бороться с реализациями в этой и других библиотеках и языках; и, если возможно, следует решить проблему, заставив программное обеспечение правильно обрабатывать отсутствующий элемент. Это неприятный побочный эффект отсутствия явной схемы (как в XML), поэтому ни одна библиотека синтаксического анализа не имеет указаний «заполнить» пустое значение, когда ключ отсутствует.

Edwin Buck 11.12.2020 13:53

Если вы можете переключить библиотеку синтаксического анализатора на circe, вы можете справиться с этими типами неверных данных.

Учитывая, что у вас есть модель данных

import io.circe.generic.semiauto._
import io.circe.parser.decode
import io.circe.{Decoder, Json}

case class Languages(languages: Seq[Language])
case class Language(name: String, is_active: String, completeness: Option[String])

Вы можете определить отказоустойчивый декодер последовательностей, который будет пропускать неверные данные, а не завершать синтаксический анализ целиком.

def tolerantSeqDecoder[A: Decoder]: Decoder[Seq[A]] = Decoder.decodeSeq(Decoder[A]
  .either(Decoder[Json])).map(_.flatMap(_.left.toOption))

и остальное...

val jsonString = """
  {
    "languages": [
    {
        "name": "English",
        "is_active": "true",
        "completeness": "asdf"
    },
    {
        "name": "Latin",
        "is_active": "asdf",
        "completeness": "232"
    },
    {
      "name": "Latin",
      "is_active": "0009"
    },
    "error"
  ]
  }
"""

val languageDecoder = deriveDecoder[Language]
implicit val tolerantDecoder =  tolerantSeqDecoder[Language](languageDecoder)
implicit val languagesDecoder = deriveDecoder[Languages]

val parsed = decode[Languages](jsonString)
println(parsed)

вне:

Right(Languages(List(Language(English,true,Some(asdf)), Language(Latin,asdf,Some(232)), Language(Latin,0009,None))))

Такой подход предложил один из разработчиков circe: Как игнорировать сбои декодирования в массиве JSON?

Другие вопросы по теме