0

I am quite new in scala.js world so I decided to try it out on some small examples and one of them is quite simple get request with parsing of returning json back into scala entity.

Please find code which does it below:

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) returns the following json:

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

And when everything comes down to the

read[List[Post]](stringify)

I get the following exception:

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

So the question is: is anything there that is done wrong? Is there some valid reason for such behavior?

Version of library used:

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

EDIT:

Adding entity itself:

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

EDIT 2:

The following code produces the same error:

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

Thanks in advance for clarification.

tkachuko
  • 1,956
  • 1
  • 13
  • 20

2 Answers2

2

Well, actually the correct answer turned out to be here: upickle read from scalaJS - upickle.Invalid$Data: String (data: 1)

String is only partially correct answer. You can also use Double (at least you get free conversion from actual long for free on scala side).

So I ended up with the following entity which works just fine:

case class Post(title: String,
                  content: String,
                  tags: List[String] = List.empty,
                  created: Double = System.currentTimeMillis())
Community
  • 1
  • 1
tkachuko
  • 1,956
  • 1
  • 13
  • 20
0

uPickle serializes Longs as strings in JSON, because JavaScript numbers cannot represent all Longs.

Therefore, the created field of your object should be the string "1474606780004".

sjrd
  • 21,805
  • 2
  • 61
  • 91
  • Thanks for your reply. For me `created` is just a timestamp. Will uPickle be able to handle LocalDateTime from java 8 date/time API for example? – tkachuko Jun 08 '16 at 19:23
  • Also from uPickle web site: Out of the box, uPickle supports writing and reading the following types: Boolean, Byte, Char, Short, Int, **Long**, Float, Double. Why does it happen then that library is not able to work with case class that has `Long` field? – tkachuko Jun 08 '16 at 19:24
  • "uPickle serializes Longs as strings in JSON", - not true. `write[List[Post]](List(post))` produces the same exception so I would better say that it does not work with `Long` type at all. – tkachuko Jun 08 '16 at 19:28
  • should I create separate question regarding issue with `write` in `EDIT 2` of the original question or you will provide explanation in the same thread? – tkachuko Jun 08 '16 at 21:14
  • And also, when I do use jackson library to create json and native js to parse it, somehow I do not get this kind of problem ("JavaScript numbers cannot represent all Longs") – tkachuko Jun 09 '16 at 01:21