如何用json4s将含JSON字符串字段的Case Class序列化为标准JSON?
问题描述
我定义了如下Case Class:
case class Data(a: String, b: String)
其中a和b的取值均为复杂JSON字符串。当我执行compact(render(data))进行序列化时,得到的JSON包含换行符和转义双引号,示例输出如下:
{"a":"\n{\"A29ebM5zRGu0UU1xNnfoCeQP\":{\"entity\":{\"timestamp\":\"2024-06-22T00:07:58.806Z\",\"_aep_stage_va6_appliedml\":{\"userid\":\"58874485546249370541145051099296067917\"},\"_id\":\"00031af8-cd81-4a95-b5a8-7bb13a419ea8\",\"directMarketing\":{\"clicks\":null,\"emailDelivered\":{\"value\":1.0},\"emailVisitorID\":\"synthetic-user-64415@adobe.com\",\"hashedEmail\":\"809rzuGYiM\",\"messageID\":\"5ff74428-65de-448c-9b4e-fee235e3a9fc\",\"offerOpens\":null,\"opens\":null,\"sends\":{\"value\":1.0}},\"eventMergeId\":null,\"eventType\":\"directMarketing.emailSent\",\"producedBy\":\"databricks-synthetic\",\"web\":null}}}\n"}
我期望得到不含换行符和转义双引号的标准JSON,请问最简洁的实现方式是什么?
解决方案
问题根源是Data类将a、b按普通字符串序列化,导致JSON字符串被二次转义。要生成标准JSON,需先把a、b的JSON字符串解析为JSON AST,再参与整体序列化。
假设使用spray-json(由compact(render)推断),提供两种简洁实现方式:
方式1:修改Case Class类型
直接将a、b的类型改为JsValue,避免二次转义:
import spray.json._ // 调整Case Class定义 case class Data(a: JsValue, b: JsValue) // 解析原始JSON字符串为JsValue val rawA = """你的复杂JSON字符串""" val parsedA = rawA.parseJson val rawB = """你的另一个复杂JSON字符串""" val parsedB = rawB.parseJson // 构造实例并序列化 val data = Data(parsedA, parsedB) val result = compact(render(data))
方式2:自定义JsonFormat(保留原Case Class)
如果不想修改原Data类,可自定义序列化规则,自动解析字符串为JSON:
import spray.json._ import DefaultJsonProtocol._ case class Data(a: String, b: String) // 自定义JsonFormat implicit val dataFormat: RootJsonFormat[Data] = new RootJsonFormat[Data] { override def write(obj: Data): JsValue = JsObject( "a" -> obj.a.parseJson, "b" -> obj.b.parseJson ) override def read(json: JsValue): Data = { val obj = json.asJsObject Data( obj.fields("a").compactPrint, obj.fields("b").compactPrint ) } } // 序列化 val data = Data(rawA, rawB) val result = data.toJson.compactPrint
两种方式最终生成的JSON都会将a、b的内容直接作为JSON对象嵌入,不会出现转义双引号和多余换行。
内容的提问来源于stack exchange,提问作者Sadhna Jain
相关产品推荐
相关产品推荐

