将Json数组反序列化为Scala对象
我在尝试将JSON数组反序列化为Scala对象时遇到了很大的问题将Json数组反序列化为Scala对象,json,scala,playframework,gson,jackson,Json,Scala,Playframework,Gson,Jackson,我在尝试将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"
[{"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(jacksonscala包装器)、sjson、flexjson。他们都没有工作过。我这里有一份客户名单。列出[客户]
这是我得到的最接近的结果:
val array = new JsonParser().parse( customers ).getAsJsonArray()
这给了我4个数组。但它显然没有给我一个客户对象。我试过杰克森
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()
}
}
谢谢您的帮助。我知道使用gson时,您需要的是数组而不是scala.List。我建议你打一针。我认为,您应该将它与gson.fromJson一起使用。我使用Lift的目的是,它可以轻松地解析JSON并将值提取到case类中。它被打包为一个单独的jar,因此您不需要整个lift框架来使用它
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在case类中定义了任何可选字段。我注意到在您的代码中,对象缺少user\u id字段,如果user\u id字段声明为
Int
,而不是Option[Int]
,则会导致解析错误。使用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))
您也可以尝试Jerkson=Jackson+Scala
即使我对包含“-”的特殊JSON字段有问题,也很容易使用
我最近在推特上看到一个小图图:我现在已经被它逼疯了,我尝试了GSON、Lift-Json、Sjson,最后终于找到了和平 以下是我如何将其与游戏结合使用:
除了尝试制作Jerkson(据我所知,这是一个很好的库),您还可以尝试Jackson的——模块是Jackson扩展到处理第三方数据类型以及本机数据类型和其他JVM语言构造的正式方式。 (这并不是说这比Jerkson更正式,只是有许多有用的Jackson扩展模块,许多开发人员并不熟悉)
Scala模块的问题在主要邮件列表中讨论(user@jackson.codehaus.org); 您可能已经找到了可以修复的边缘情况。我已经编写了一个解析器/验证器dsl,它允许您显式解决任何类型的擦除问题。开箱即用,它处理大小写类、元组、选项、列表、映射、joda DateTime、管道到函数、多键映射和键名重新映射 它使用Jackson解析器
使用scala、play库和代码非常简单
import play.api.libs.json.{Format, Json}
case class Customer(name:String, city:String, address:String, id:Int)
object Customer {
implicit val jsonFormat: Format[Customer] = Json.format(Customer)
}
val jsonDef = Json.parse(<json-string>)
val customers = jsonDef.as[List[Customer]]
import play.api.libs.json.{Format,json}
案例类客户(名称:String,城市:String,地址:String,id:Int)
目标客户{
隐式val jsonFormat:Format[Customer]=Json.Format(Customer)
}
val jsonDef=Json.parse()
val customers=jsonDef.as[List[Customer]]
客户
是客户
对象的列表。谢谢您的建议。我认为潜在的问题是这些库都不知道如何从Anorm反序列化Pk对象。知道吗?谢谢。我不知道Pk对象到底是什么,但是你可以通过创建一个类似于隐式def int2Pk(I:Int):Pk[Int]=…
的东西来绕过它。Scala将在编译时使用该函数自动处理转换。嘿,谢谢你的回答。这实际上让我更进一步了。问题是gson不知道如何反序列化Pk对象。谢谢。是的,gson不能很好地处理特定于scala的声明。Id是一个接受参数的case类,gson不能很好地处理这些参数。您可以忽略id字段(标记为transient),还是在序列化输出中确实需要它?我想sjson应该在处理scala方面做得更好(不过我个人没有使用过)。如果Gson不能很好地处理scala,请Gson的作者添加支持(或者尝试提供支持的扩展)也许是有意义的?同时,使用与Scala一起工作的soemthing(有多个备选建议),这也是一个很好的答案。虽然这对于大型对象来说是不可维护的。你是对的,但是它提供了很多控制来映射到我们想要的任何类型。同时,在Groovy的围栏上,有一个“def foo=new foo(bar:1,baz:'hey')作为JSON”并且你有一个对象的JSON表示。Scala真的,真的需要这种简洁的Scala对象到JSON的转换。无法获取任意复杂的对象图并轻松序列化为JSON,这使得Scala REST成为PITA。也许lift json或Jerkson(维护者显然擅离职守,顺便说一句)可以做到这一点,但不管怎样,尾巴都会摇狗;如果一个case类是在一行中定义的,为什么将它转换成JSON需要20多行呢?然后你有30多个域类,很有趣…现在建议不要使用它,因为库已经切换到Jackson 2,而Jarkson还没有升级。注释将发生冲突。