在Scala中转换JSON对象时出现问题
我试图使用json4s库在Scala中创建一个类序列化的简单示例,但即使在internet上广泛搜索了它,不幸的是,我也找不到任何满意的示例来解决我的问题 基本上,我有一个名为在Scala中转换JSON对象时出现问题,json,scala,parsing,json4s,Json,Scala,Parsing,Json4s,我试图使用json4s库在Scala中创建一个类序列化的简单示例,但即使在internet上广泛搜索了它,不幸的是,我也找不到任何满意的示例来解决我的问题 基本上,我有一个名为Person的简单类,我想从JSON字符串中提取这个类的一个实例 case class Person( val name: String, val age: Int, val children: Option[List[Person]] ) 所以当我这样做的时候: val jsonStr = "{
Person
的简单类,我想从JSON字符串中提取这个类的一个实例
case class Person(
val name: String,
val age: Int,
val children: Option[List[Person]]
)
所以当我这样做的时候:
val jsonStr = "{\"name\":\"Socrates\", \"age\": 70}"
println(Serialization.read[Person](jsonStr))
我得到这个输出:
"Person(Socrates,70,None)" // works fine!
但当JSON字符串中没有age参数时,会出现以下错误:
线程“main”org.json4s.package$MappingException中的异常:年龄没有可用值
我知道Person
类在其构造函数中有两个必需的参数,但我想知道是否有方法通过解析器或类似的东西进行这种转换
另外,我也尝试过制作这个解析器,但没有成功
提前感谢您的帮助。假设您不想通过将其类型设置为
选项来选择年龄,那么您可以通过扩展CustomSerializer[Person]
来编写自定义序列化程序。自定义序列化程序将函数从格式
转换为PartialFunction[JValue,Person]
(您的Person
反序列化程序)和PartialFunction[Any,JValue]
(您的序列化程序)的元组
假设Person.DefaultAge
是要为年龄设置的默认值(如果未指定年龄),则自定义序列化程序的外观如下所示:
object PersonSerializer extends CustomSerializer[Person](formats => ( {
case JObject(JField("name", JString(name)) :: JField("age", JInt(age)) :: Nil) => Person(name, age.toInt, None)
case JObject(JField("name", JString(name)) :: JField("age", JInt(age)) :: JField("children", JArray(children)) :: Nil) => Person(name, age.toInt, Some(children map (child => formats.customDeserializer(formats).apply(TypeInfo(classOf[Person], None), child).asInstanceOf[Person])))
case JObject(JField("name", JString(name)) :: Nil) => Person(name, Person.DefaultAge, None)
case JObject(JField("name", JString(name)) :: JField("children", JArray(children)) :: Nil) => Person(name, Person.DefaultAge, Some(children map (child => formats.customDeserializer(formats).apply(TypeInfo(classOf[Person], None), child).asInstanceOf[Person])))
}, {
case Person(name, age, None) => JObject(JField("name", JString(name)) :: JField("age", JInt(age)) :: Nil)
case Person(name, age, Some(children)) => JObject(JField("name", JString(name)) :: JField("age", JInt(age)) :: JField("children", formats.customSerializer(formats).apply(children)) :: Nil)
}))
这可能可以简化,因为有很多重复。此外,可能还有更好的方法递归调用序列化/反序列化 当没有“age”参数时,解析JSON的结果是什么?显然,您需要为age使用选项[Int]type或创建自定义序列化程序:@dan getz,我将从第三方应用程序接收这些JSON字符串,因此我不能保证所有参数都会出现在它们的请求中,因此,我只是想找出使解析器健壮的选项(我一周前才开始学习Scala语言)。@sap1ens,正如我所说,我试图使用这个精确的示例来制作这个解析器,但没有成功。无论如何,谢谢。“我的选项是什么?”您可以保留现有的异常,抛出不同的异常,返回一个选项
,返回一个特殊值,使用选项
作为年龄
参数,使用一个特殊的年龄
数字表示“未指定”,返回一个尝试
或任何一个。。。这一清单不胜枚举。您是在请求帮助编写解析器,还是在决定您的代码首先应该做什么?非常感谢,@KuluLimpa!它像我预料的那样轻柔地工作。