我遇到的问题与此处描述的非常相似:组合类型和字段序列化器
case class(id: Option[UUID], otherValue:String, … )
Run Code Online (Sandbox Code Playgroud)
相关问题的答案将允许我编写自己的格式,但我很好奇是否已经有一个UUID格式隐藏在json4s中的某个地方.我猜想正确的导入可以解决UUID的这个问题,我有点惊讶没有找到任何东西.
我想念它,还是不存在?
在json4s的例子和文档中,我经常看到成语
compact(render(jval))
Run Code Online (Sandbox Code Playgroud)
和
pretty(render(jval))
Run Code Online (Sandbox Code Playgroud)
我不认为我实际上看到过一个直接应用于生成的代码的紧凑或漂亮的例子JValue,但我不清楚render这里做了什么.渲染有类型JValue => JValue,我没有看到它制作和运行有任何明显的差异
json.take(100000).filter(x => compact(render(x)) != compact(x))
Run Code Online (Sandbox Code Playgroud)
我的一些数据返回一个空的空集合.
什么是render真正做到?
我有一个非常简单的例子:
import org.json4s._
import org.json4s.native.JsonMethods._
import org.json4s.JsonDSL._
val json = ("english" -> JString("serialization")) ~ ("japanese" -> JString("??????????"))
println(pretty(render(json)))
Run Code Online (Sandbox Code Playgroud)
我得到的是:
{
"english":"serialization",
"japanese":"\u30b7\u30ea\u30a2\u30e9\u30a4\u30bc\u30fc\u30b7\u30e7\u30f3"
}
Run Code Online (Sandbox Code Playgroud)
我想要的是这个(完全有效的AFAIK)JSON:
{
"english":"serialization",
"japanese":"??????????"
}
Run Code Online (Sandbox Code Playgroud)
我现在找不到它,但我想我已经读过JSON只需要两个特殊的UTF-8字符进行转义的地方.
查看渲染代码,看起来Strings总是为非ASCII字符获得额外的双重转义.
任何人都知道如何在没有双重转义所有UTF-8扩展字符的情况下获得有效的JSON?这似乎是一个非常类似的问题:为什么PHP json_encode函数将UTF-8字符串转换为十六进制实体?
更新:事实证明这是json4s中的一个未解决的问题,有一个未决的PR#327关闭了PR#339,而PR#339又在2016年2月13日的提交中合并到3.4版本分支中.
我正在试验json4s库(基于lift-json).我想做的一件事是将JSON字符串解析为AST,然后对其进行操作.
例如,我想要一个字段(如果它不存在则将字段插入AST,或者如果它存在则更新其值).
我无法在文档中找到如何做到这一点.尝试了可用的方法,我提出了以下哪些有效,但感觉很笨拙.
import org.json4s._
import org.json4s.JsonDSL._
import org.json4s.native.JsonMethods._
object TestJson {
implicit val formats = DefaultFormats
def main(args: Array[String]): Unit = {
val json = """{"foo":1, "bar":{"foo":2}}"""
val ast = parse(json).asInstanceOf[JObject]
println( upsertField(ast, ("foo" -> "3")) )
println( upsertField(ast, ("foobar" -> "3")) )
}
def upsertField(src:JObject, fld:JField): JValue = {
if(src \ fld._1 == JNothing){
src ~ fld
}
else{
src.replace(List(fld._1), fld._2)
}
}
}
Run Code Online (Sandbox Code Playgroud)
我不喜欢它有很多原因:
parse(json)转换为JObjectupsertField函数的结果是a JValue,如果我想进一步操作对象,我将不得不重新制作upsertField功能只是感觉很unelegant有没有更好的方法来转换AST? …
基本上,我必须使用Spark分析HDFS上的一些复杂的JSON.
我使用"for comprehensions"来(预)过滤json的jSON和"extract"方法,将它包装成一个case类
这个工作正常!
def foo(rdd: RDD[String]) = {
case class View(C: String,b: Option[Array[List[String]]], t: Time)
case class Time($numberLong: String)
implicit val formats = DefaultFormats
rdd.map { jsonString =>
val jsonObj = parse(jsonString)
val listsOfView = for {
JObject(value) <- jsonObj
JField(("v"), JObject(views)) <- value
normalized <- views.map(x => (x._2))
} yield normalized
}
Run Code Online (Sandbox Code Playgroud)
到现在为止还挺好!
当我尝试将(预)过滤的JSON提取到我的CaseClass时,我得到这个:
线程"main"中的异常org.apache.spark.SparkException:由于阶段失败而中止作业:任务不可序列化:java.io.NotSerializableException:org.json4s.DefaultFormats $
这里带有提取的代码:
def foo(rdd: RDD[String]) = {
case class View(C: String,b: Option[Array[List[String]]], t: Time)
case class Time($numberLong: String)
implicit val formats = DefaultFormats …Run Code Online (Sandbox Code Playgroud) 我目前正在尝试使用json4s(scala)从json数组中提取信息.
示例数据如下:
val json = """
[
{"name": "Foo", "emails": ["Foo@gmail.com", "foo2@gmail.com"]},
{"name": "Bar", "emails": ["Bar@gmail.com", "bar@gmail.com"]}
]
"""
Run Code Online (Sandbox Code Playgroud)
我的代码如下:
case class User(name: String, emails: List[String])
case class UserList(users: List[User]) {
override def toString(): String = {
this.users.foldLeft("")((a, b) => a + b.toString)
}
}
val obj = parse(json).extract[UserList]
printf("type: %s\n", obj.getClass)
printf("users: %s\n", obj.users.toString)
Run Code Online (Sandbox Code Playgroud)
输出结果是:
type: class UserList
users: List()
Run Code Online (Sandbox Code Playgroud)
似乎没有正确检索数据.我的代码有问题吗?
更新:根据@Kulu Limpa的建议工作.
有没有一种简单的方法将给定的Row对象转换为json?
发现这有关将整个Dataframe转换为json输出: Spark Row到JSON
但我只想将一行转换为json.这是我想要做的伪代码.
更确切地说,我在数据帧中读取json作为输入.我正在生成一个主要基于列的新输出,但是有一个json字段用于所有不适合列的信息.
我的问题是什么是编写这个函数最简单的方法:convertRowToJson()
def convertRowToJson(row: Row): String = ???
def transformVenueTry(row: Row): Try[Venue] = {
Try({
val name = row.getString(row.fieldIndex("name"))
val metadataRow = row.getStruct(row.fieldIndex("meta"))
val score: Double = calcScore(row)
val combinedRow: Row = metadataRow ++ ("score" -> score)
val jsonString: String = convertRowToJson(combinedRow)
Venue(name = name, json = jsonString)
})
}
Run Code Online (Sandbox Code Playgroud)
Psidom的解决方案:
def convertRowToJSON(row: Row): String = {
val m = row.getValuesMap(row.schema.fieldNames)
JSONObject(m).toString()
}
Run Code Online (Sandbox Code Playgroud)
仅当Row只有一个级别而不是嵌套Row时才有效.这是架构:
StructType(
StructField(indicator,StringType,true),
StructField(range,
StructType(
StructField(currency_code,StringType,true),
StructField(maxrate,LongType,true),
StructField(minrate,LongType,true)),true))
Run Code Online (Sandbox Code Playgroud)
还尝试了Artem的建议,但是没有编译:
def row2DataFrame(row: Row, …Run Code Online (Sandbox Code Playgroud) 我正在使用json4s 3.2.11和Scala 2.11。
我使用定义了一个枚举sealed trait,并为其使用了一个自定义序列化器:
import org.json4s.CustomSerializer
import org.json4s.JsonAST.JString
import org.json4s.DefaultFormats
import org.json4s.jackson.Serialization
sealed trait Foo
case object X extends Foo
case object Y extends Foo
object FooSerializer
extends CustomSerializer[Foo](
_ =>
({
case JString("x") => X
case JString("y") => Y
}, {
case X => JString("x")
case Y => JString("y")
})
)
Run Code Online (Sandbox Code Playgroud)
这很棒,添加到以下格式后效果很好:
{
implicit val formats = DefaultFormats + FooSerializer
Serialization.write(X) // "x"
}
Run Code Online (Sandbox Code Playgroud)
这很棒!
如果未将序列化程序添加到格式中,则json4s将使用反射来创建字段的默认表示形式,这对于这些object没有字段的s 极为不利。它无声地执行此操作,似乎无法控制它。
{
implicit val formats = …Run Code Online (Sandbox Code Playgroud) 我想支持提交到同一网址的几种不同的内容类型:
例如:
application/x-www-form-urlencoded,multipart/form-data,application/json
我想做的事情如下:
post {
contentType(`application/x-www-form-urlencoded`) |
contentType(`multipart/form-data`) {
// user POSTed a form
entity(as[MyCaseClass]) { data =>
complete { data.result }
}
} ~ contentType(`application/json`) {
// user POSTed a JSON object
entity(as[MyCaseClass]) { data =>
complete { data.result }
}
}
}
Run Code Online (Sandbox Code Playgroud)
我认为可能有一些方法可以使用自定义编组和解组,但我只需要在我的服务中的一两个位置,这看起来很简单.有人可以帮忙吗?
我有一个包含许多成员的案例类,其中两个是非原始的:
import com.twitter.util.Duration
case class Foo(
a: Int,
b: Int,
...,
y: Int,
z: Int,
timeoutSeconds: Duration,
runtimeMinutes: Duration)
Run Code Online (Sandbox Code Playgroud)
我想将以下JSON反序列化为此case类的实例:
{
"a": 1,
"b": 2,
// ...
"y": 42,
"z": 43,
"timeoutSeconds": 30,
"runtimeMinutes": 12,
}
Run Code Online (Sandbox Code Playgroud)
通常,我会写json.extract[Foo].然而,MappingException由于timeoutSeconds和,我得到了明显的runtimeMinutes.
我看过FieldSerializer,它允许在AST上进行字段转换.但是,它不够,因为它只允许AST转换.
我也看过扩展CustomSerializer[Duration],但没有办法反省哪个JSON密钥正在被处理(timeoutSeconds或runtimeMinutes).
我也可以尝试延长CustomSerializer[Foo],但后来我将有很多的样板代码,用于提取值a,b,..., z.
理想情况下,我需要一些PartialFunction[JField, T]作为反序列化器的东西,以便我可以写:
{
case ("timeoutSeconds", JInt(timeout) => timeout.seconds
case ("runtimeMinutes", JInt(runtime) => …Run Code Online (Sandbox Code Playgroud) json4s ×10
scala ×9
json ×6
apache-spark ×2
case-class ×1
hdfs ×1
lift-json ×1
reflection ×1
spray ×1
spray-dsl ×1
utf-8 ×1