2011-11-01 92 views
4

我一直有尝试反序列化JSON数组到Scala的对象反序列化JSON阵列分成Scala的对象

 [{"name":"Cool","city":"College Park","address":"806","id":1},{"name":"Mars ","city":"Durham","address":"12","id":2},{"name":"Something","city":"Raleigh 
","address":"","id":3},{"name":"test","city":"","address":"","id":5}] 

我试图GSON,jerkson(杰克逊阶包装器),sjson,flexjson重大问题。他们都没有工作。我在这里有一份客户名单。列表[客户]。

这是我所得到的最接近:

val array = new JsonParser().parse(customers).getAsJsonArray() 

这给了我4个阵列。它显然没有给我一个客户对象。我试过Jerkson。

val array = parse[List[Customer]](customers) 

但我明白了。

GenericSignatureFormatError occured : null 

我只是想在Java中找到一个简单的方法。

这是我的Scala类。

case class Customer(
    id : Pk[ Int ], 
    name : String, 
    address : Option[ String ], 
    city : Option[ String ], 
    state : Option[ String ], 
    user_id : Int) 

    object Customer extends Magic[ Customer ](Option("Customer")) { 

    def apply(name : String, address : String, city : String, state : String, user_id : Int) = { 
     new Customer(NotAssigned, name, Some(address), Some(city), Some(state), user_id) 
    } 

    def delete(id : Int) = { 
     SQL("DELETE from Customer where id = {id}").onParams(id).executeUpdate() 
    } 

} 

感谢您的任何帮助。

回答

4

随着GSON,你可以写你自己的JSON的读者:

case class Customer(id: Int, name: String, address: Option[String], 
    city: Option[String], state: Option[String], user_id: Int) 

object CustomerJsonReader { 

    def read(in: Reader) = readCustomers(new JsonReader(in)) 

    def readCustomers(reader: JsonReader) = { 
    val customers = new ListBuffer[Customer] 
    reader.beginArray() 
    while (reader.hasNext()) { 
     customers += readCustomer(reader) 
    } 
    reader.endArray() 
    customers toList 
    } 

    def readCustomer(reader: JsonReader): Customer = { 
    var id = 0 
    var customerName = "" 
    var address: Option[String] = None 
    var city: Option[String] = None 
    var state: Option[String] = None 
    var userId = 0 

    reader.beginObject() 
    while (reader.hasNext()) { 
     val name = reader.nextName() 
     name match { 
     case "id" => id = reader.nextInt() 
     case "address" => address = Some(reader.nextString()) 
     case "state" => state = Some(reader.nextString()) 
     case "user_id" => userId = reader.nextInt() 
     case "name" => customerName = reader.nextString() 
     case "city" => city = Some(reader.nextString()) 
     case _ => reader.skipValue() 
     } 
    } 
    reader.endObject() 
    Customer(id, customerName, address, city, state, userId) 
    } 

} 

val json = 
    """ 
    [{"name":"Cool","city":"College Park","address":"806","id":1}, 
    {"name":"Mars ","city":"Durham","address":"12","id":2}, 
    {"name":"Something","city":"Raleigh ","address":"","id":3}, 
    {"name":"test","city":"","address":"","id":5}] 
    """ 

val customers: List[Customer] = 
    CustomerJsonReader.read(new StringReader(json)) 
+0

这也是一个很好的答案。尽管这可能会对大对象无法维护。 –

+0

你是对的,但它可以很好地控制我们想要的任何类型。 –

+0

同时,在栅栏的Groovy一边,“def foo = new Foo(bar:1,baz:'hey')为JSON”,并且您有对象的JSON表示。真的,Scala真的需要这种简洁的Scala对象来进行JSON转换。无法获取任意复杂的对象图并轻松地序列化为JSON使得Scala REST成为PITA。也许lift-json或Jerkson(维护者显然是awol,顺便说一句)可以做到这一点,但尾巴摇摆不顾;如果case类在1行中定义,为什么将它转换为/从JSON需要20行加号?然后你有30多个领域类,有趣... – virtualeyes

3

我知道用gson,你需要数组而不是scala.List。我会建议给那一枪。我认为你应该使用gson.fromJson。

+0

嘿感谢这个答案。这实际上让我进一步了一点。问题是gson不知道如何反序列化Pk对象。谢谢。 –

+0

是的gson不能很好地处理scala特定的声明。 Id是一个需要参数的案例类,没有一个使用gson处理得很好。你可以忽略id字段(标记为瞬态),还是你肯定需要它在你的序列化输出中?我猜sjson应该更好地处理scala(尽管我没有亲自使用它)。 – aishwarya

+0

如果Gson不能很好地处理Scala,那么请问Gson作者是否可以添加支持(或者尝试做出贡献的扩展)?并在此同时使用与Scala一起工作的东西(其中有多个备用建议) – StaxMan

1

为此,我使用Lift的json library,它可以轻松让您解析JSON并将值提取到案例类中。它作为一个单独的jar包装,所以你不需要整个提升框架来使用它。

import net.liftweb.json._ 
import net.liftweb.json.JsonDSL._ 

implicit val formats = DefaultFormats 

val json: String = "[{...." 
val parsed: JValue = parse(json) 
val customers: List[Customer] = parsed.extract[List[Customer]] 

只要确保在使用Option的案例类中定义了任何可选字段。我在代码中注意到对象缺少user_id字段,如果user_id字段被声明为Int而不是Option[Int],则会导致解析错误。

+0

感谢您的建议。我认为潜在的问题是这些库中没有一个知道如何从Anorm中去除Pk对象。知道这件事吗?谢谢。 –

+0

我不确切知道Pk对象是什么,但是你可以通过创建一个[隐式转换函数]来解决它(http://pietrowski.info/2009/07/scala-implicit-conversion/) ,看起来像'implicit int2Pk(i:Int):PK [Int] = ...'。 Scala将在编译时使用该函数来自动处理转换。 –

1
从试图让Jerkson(这是从我所听到的用一个伟大的图书馆)

一旁,也可以试用Jackson的Scala module - 模块是Jackson扩展的官方方式,用于处理第三方数据类型以及本机数据类型和其他JVM语言的结构。 (这并不是说这比Jerkson更官方,只是有很多有用的Jackson扩展模块,许多开发人员并不熟悉)

Scala模块的问题在Jackson主要邮件列表上讨论过(user @ jackson .codehaus.org);你可能找到了一个可以修复的边缘案例。

0

我写了一个解析器/验证器dsl,它允许您明确地解决任何类型的擦除问题。开箱即用,它处理大小写类,元组,选项,任一,列表,映射,约达DatetTime,管道到函数,多键映射和键名重新映射。

它采用了杰克逊解析器

https://github.com/HigherState/jameson