【问题标题】:upickle: invalid string value during deserializationupickle:反序列化期间的无效字符串值
【发布时间】:2016-10-07 22:50:18
【问题描述】:

我是 scala.js 领域的新手,所以我决定尝试一些小示例,其中一个是非常简单的获取请求,将返回的 json 解析回 scala 实体。

请在下面找到执行此操作的代码:

def loadAndDisplayPosts(postsElement: Element) = {
  jQuery.get(
    url = "/posts",
    success = {
      (data: js.Any) =>
        val stringify = JSON.stringify(data)
        console.log(stringify)
        val posts = read[List[Post]](stringify)
        console.log(posts.size)
        posts.map(render).foreach(postsElement.appendChild)
    }
  )
}

console.log(stringify) 返回以下 json:

[
  {
    "title": "Some fancy title",
    "content": "some very long string with \"escaped\" characters",
    "tags": [
      "algorithms"
    ],
    "created": 1474606780004
  }
]

当一切都归结为

read[List[Post]](stringify)

我得到以下异常:

upickle.Invalid$Data: String (data: 1474606780004)

所以问题是:有什么做错了吗?这种行为是否有正当理由?

使用的库版本:

"com.lihaoyi" %%% "upickle" % "0.4.1"

编辑:

添加实体本身:

case class Post(title: String,
                  content: String,
                  tags: List[String] = List.empty,
                  created: Long = System.currentTimeMillis())

编辑 2:

以下代码产生相同的错误:

val post = Post("Some title", "some \"content\"", List("algorithms"), 1474606780004L)
val json = write[List[Post]](List(post))

提前感谢您的澄清。

【问题讨论】:

  • 我相信 upickle 将Longs 序列化为 JSON 字符串。尝试在手动实例化的帖子列表上调用write,并将输出与您的stringify 字符串进行比较。
  • 作为替代方案:你能不能调用readJs而不是read,传递data而不是stringify
  • 将回调签名更改为数据:Js.Value 并调用 readJs 方法会导致此异常:scala.scalajs.runtime.UndefinedBehaviorError:检测到未定义的行为:[object Object],[object Object],[ object Object],[object Object],[object Object] 不是 upickle.Js$Value 的实例
  • 编辑的问题,写的例子也不起作用
  • 你能把write的结果贴出来吗?

标签: scala scala.js upickle


【解决方案1】:

嗯,原来正确答案在这里:upickle read from scalaJS - upickle.Invalid$Data: String (data: 1)

String 只是部分正确答案。您还可以使用 Double(至少您可以 在 scala 端免费从实际 long 获得免费转换)。

所以我最终得到了以下可以正常工作的实体:

case class Post(title: String,
                  content: String,
                  tags: List[String] = List.empty,
                  created: Double = System.currentTimeMillis())

【讨论】:

    【解决方案2】:

    uPickle 将Longs 序列化为 JSON 中的字符串,因为 JavaScript 数字不能代表所有 Longs。

    因此,您对象的created 字段应该是字符串 "1474606780004"

    【讨论】:

    • 感谢您的回复。对我来说created 只是一个时间戳。例如,uPickle 是否能够处理来自 java 8 日期/时间 API 的 LocalDateTime?
    • 同样来自 uPickle 网站:开箱即用,uPickle 支持写入和读取以下类型:Boolean、Byte、Char、Short、Int、Long、Float、Double .为什么会发生这种情况,然后该库无法使用具有 Long 字段的案例类?
    • "uPickle 将 Long 序列化为 JSON 中的字符串",- 不正确。 write[List[Post]](List(post)) 产生相同的异常,所以我最好说它根本不适用于 Long 类型。
    • 我是否应该在原始问题的EDIT 2 中针对write 的问题创建单独的问题,或者您将在同一线程中提供解释?
    • 而且,当我确实使用杰克逊库创建 json 和原生 js 来解析它时,不知何故我没有遇到这种问题(“JavaScript 数字不能代表所有 Longs”)
    猜你喜欢
    • 1970-01-01
    • 2018-01-13
    • 2018-10-22
    • 1970-01-01
    • 2016-12-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多