2015-09-06 70 views
2

我在我的项目中使用json4s库手动解析JSON字段的字段(没有自动反序列化到案例类)。使用json4s解析JSON中的空值

,比如我有以下JSON:

{ 
    result: "OK", 
    persons: [ 
    {name: "Alex"}, 
    {name: null} 
    ] 
} 

而且官方指南建议使用这种方法来手动解析它:

for { 
     JArray(persons) <- json/"persons" 
     JObject(person) <- persons 
     JField("name", JString(name)) <- person 
     } yield Person(name) 

的问题是,这种换理解跳过的人哪有null名称。我认为这是因为在理解中我使用了JString(name),所以它需要一些String值,而不是null

有什么办法解决这个问题吗?我只是想遍历数组并访问每个对象(即使它有null而不是一些String

回答

2

是的,你已经有了它不能工作的原因,你只需要改变模式匹配以下。

case class Person(name: String) 
// the result is actually List[Option[Person]] 
val result = 
    for { 
    JArray(persons) <- json \ "persons" 
    JObject(person) <- persons 
    // jv is JsonAST.JValue 
    JField("name", jv) <- person 
    } yield { 
    // in case of match error so add _ here 
    jv match { 
     case JString(name) => Some(Person(name)) 
     case JNull => Some(Person(null)) 
     case _ => None 
    } 
    } 

其实,有以下你提到的文档中的部分Extracting values另一种更简单的方法。

case class Person(name: String) 
import org.json4s.DefaultFormats 
implicit val formats = DefaultFormats // Brings in default date formats etc 
val result2 = (json \ "persons").extract[List[Person]] 
// List(Person(Alex), Person(null)) 
println(result2) 
+0

可以请你的答案复制到这个问题:http://stackoverflow.com/questions/25200005/extract-options-from-potentially-null-json -values-using-for表达式 我在那里打开赏金 – MyTitle

+0

我可以这么做,但认真的说我不认为这是值得你为回答“支付”300名声誉。 –

+0

也想问:我的JSON的每个字段可能都是空的,而且我有大约15个我感兴趣的字段,所以我似乎需要用这种模式匹配来替换每个字段提取(5行而不是1行)的代码)。有比模式匹配更紧凑的方式吗? 第二种方法不适合我(我在创建案例类之前进行了很多提取字段的转换) – MyTitle

0

这样做,

val r:List[Person] = for { 
    JArray(persons) <- JsonMethods.parse(json) \ "persons" 
    JObject(person) <- persons 
    //JField("name", JString(name)) <- person 
    p = Person(person.head._2) //or Person(person.find(_._1=="name").map(_._2).getOrElse(null)) 
    } yield p 

    println(r) //List(Person("Alex"), Person(null))