json4s
A single AST to be used by other scala json libraries
Json4s by json4s
I need to serialize akka events to json. Based on
"What JSON library to use in Scala?" I tried several libraries. Since my serializer should know nothing of all my concrete events, the events consisting of case classes and case objects should be serialised using reflection. json4s seems to match my requirements best.
class Json4sEventAdapter(system: ExtendedActorSystem) extends EventAdapter {
implicit val formats = Serialization.formats(FullTypeHints(List(classOf[Evt])))
override def toJournal(event: Any): Any = event match {
case e: AnyRef =>
write(e).getBytes(Charsets.UTF_8)}
override def fromJournal(event: Any, manifest: String): EventSeq = event match {
case e: Array[Byte] => {
EventSeq.single(read[Evt](new String(e.map(_.toChar))))}}
The problem using json4s is, that no matter which implementation is used Deserialization of objects produces different instances.
Since we heavily use pattern matching for the case object this breaks all our existing code.
So my question is: which JSON library could be used with scala and akka persistence when storing case objects?
Is there even one library that handles deserialization of case objects via reflection correctly? - or does anyone have a good workaround?
Source: (StackOverflow)
Is it possible to serialize object of below class using Json4s or lift or any other library?
class User(uId: Int) extends Serializable {
var id: Int = uId
var active: Boolean = false
var numTweets: Int = 0
var followers: ArrayBuffer[Int] = null
var following: ArrayBuffer[Int] = null
var userTimeline: Queue[String] = null
var homeTimeline: Queue[String] = null
var userTimelineSize: Int = 0
var homeTimelineSize: Int = 0
//var notifications: Queue[String] = null
var mentions: Queue[String] = null
var directMessages: Queue[String] = null
}
Source: (StackOverflow)
How do you create Json object with values of different types ?
I'm using spray-json
Here is the code
val images : List[JsObject] = fetchImageUrls(url).map((url: String) => {
JsObject(List(
"link_path" -> JsString(url),
"display_name" -> JsString("image"),
"size" -> JsString(""),
"modified" -> JsString(""),
"thumbnail" -> JsString(url),
"filename" -> JsString("image"),
"is_dir" -> JsBoolean(x = false),
"thumb_exists" -> JsBoolean(x = true)) )
})
val jsonAst: JsObject = JsObject(List(
"client" -> JsString("urlimages"),
"view" -> JsString("thumbnails"),
"contents" -> JsArray(images)
))
It works but looks really heavy. Is there a way to define json with code like this ?
val images : List[List[(String, Any)]] = fetchImageUrls(url).map((url: String) => {
List(
"link_path" -> url,
"display_name" -> "image",
"size" -> "",
"modified" -> "",
"thumbnail" -> url,
"filename" -> "image",
"is_dir" -> false,
"thumb_exists" -> true)
})
val jsonAst = List(
"client" -> "urlimages",
"view" -> "thumbnails",
"contents" -> images
).toJson
It doesn't work saying that
Cannot find JsonWriter or JsonFormat type class for List[(String, Object)]
).toJson
^
Which I get, type of each field is not defined at compile time. But why wouldn't it work if serializer does pattern matching anyway ?
Thanks!
Source: (StackOverflow)
I am currently trying to extract the information from a json array using json4s (scala).
An example data is as follows:
val json = """
[
{"name": "Foo", "emails": ["Foo@gmail.com", "foo2@gmail.com"]},
{"name": "Bar", "emails": ["Bar@gmail.com", "bar@gmail.com"]}
]
"""
And my code is as follows:
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)
The output turns out to be:
type: class UserList
users: List()
It seems that the data is not correctly retrieved. Is there any problem with my code?
UPDATE:
It works according to the suggestion of @Kulu Limpa.
Source: (StackOverflow)
I'm trying to prevent one of the properties of a Scala case class
being serialised. I've tried annotating the property in question with the usual @JsonIgnore
and I've also tried attaching the @JsonIgnoreProperties(Array("property_name"))
to the case class
. Neither of which seem to achieve what I want.
Here's a small example:
import org.json4s._
import org.json4s.jackson._
import org.json4s.jackson.Serialization
import org.json4s.jackson.Serialization.{read, write}
import com.fasterxml.jackson.annotation._
object Example extends App {
@JsonIgnoreProperties(Array("b"))
case class Message(a: String, @JsonIgnore b: String)
implicit val formats = Serialization.formats(NoTypeHints)
val jsonInput = """{ "a": "Hello", "b":"World!" }"""
val message = read[Message](jsonInput)
println("Read " + message) // "Read Message(Hello,World!)
val output = write(message)
println("Wrote " + output) // "Wrote {"a":"Hello","b":"World!"}"
}
Source: (StackOverflow)
I've discovered that by using json4s native
<dependency>
<groupId>org.json4s</groupId>
<artifactId>json4s-native_2.10</artifactId>
<version>3.2.9</version>
</dependency>
brings scalap and scala-compiler dependencies.
Why does it need it?
Does it generate code on the fly at runtime?
Why doesn't it use macros that do this processing at compile time?
Source: (StackOverflow)
I am attempting to produce JSON in a Scala app using json4s. Fairly straight forward, Here's some sample value I put together to test it in my Scalatra app:
import org.json4s._
import org.json4s.JsonDSL._
object JsonStub {
val getPeople =
("people" ->
("person_id" -> 5) ~
("test_count" -> 5))
}
In my controller, I simply have:
import org.json4s._
import org.json4s.JsonDSL._
import org.json4s.{DefaultFormats, Formats}
class FooController(mongoDb: MongoClient)(implicit val swagger: Swagger) extends ApiStack with NativeJsonSupport with SwaggerSupport {
get ("/people", operation(getPeople)) {
JsonStub.getPeople
}
}
The output I'm seeing in the browser however, is the following:
{
"_1": "people",
"_2": {
"person_id": 5,
"test_count": 5
}
}
Any clue where the _1
and _2
keys are coming from? I was expecting this output instead:
{
"people":{
"person_id": 5,
"test_count": 5
}
}
Source: (StackOverflow)
Even after reading: Scala, problem with a jar file, I'm still a bit confused. I am trying to import some packages into my Scala file, and the interpreter is not recognizing them even after adding to classpath.
One example:
I have the import statement:
import org.json4s._
I downloaded the .jar from here: http://mvnrepository.com/artifact/org.json4s/json4s-native_2.10/3.2.4
and added to the interpreter classpath using:
scala> :cp /Users/aspangher13/Downloads/json4s-native_2.10-3.2.4.jar
Scala acknowledges the classpath:
Your new classpath is: ".:/Users/aspangher13/Downloads/json4s-native_2.10-3.2.4.jar:/Users/aspangher13/Downloads/jna-3.5.2.jar"
But still throws this error:
<console>:7: error: object scalatra is not a member of package org
import org.json4s._
Can anyone see what I'm doing wrong? Thanks!!
And as a followup, does anyone know where to find the package: JsonAST._?
Source: (StackOverflow)
In json4s examples and documentation I often see the idioms
compact(render(jval))
and
pretty(render(jval))
I do not think I have actually seen an example with compact or pretty applied directly to a code generated JValue
,
but it is not clear to me what render
is doing here.
Render has type JValue => JValue
and I do not see any obvious difference it makes
and running
json.take(100000).filter(x => compact(render(x)) != compact(x))
on some of my data returns an empty an empty collection.
What does render
actually do?
Source: (StackOverflow)
I am writing a Customer Serializer. In that Serializer I would like to somehow say: "and this thing you already know how to serialize".
My current approach looks like that:
import org.json4s.native.Serialization._
import org.json4s.JsonDSL.WithBigDecimal._
object WindowSerializer extends CustomSerializer[Window](format =>
( [omitted],
{
case Window(frame, size) =>
( "size" -> size ) ~
( "frame" -> parse(write(frame)) )
}))
That parse(write(frame))
things is both ugly and inefficient. How to fix that?
Source: (StackOverflow)
I am using Scalatra, which in turn uses Json4S to generate Json string. I receive
["A","B"]
for
List(Some("A"),None,Some("B"))
I would like to receive
["A",undefined,"B"]
How can this be fixed ?
Source: (StackOverflow)
Is it possible to make json4s not to throw exception when required field is missing ?
When I "extract" object from raw json string it throws exception like this one
org.json4s.package$MappingException: No usable value for pager
No usable value for rpp
Did not find value which can be converted into byte
at org.json4s.reflect.package$.fail(package.scala:98)
at org.json4s.Extraction$ClassInstanceBuilder.org$json4s$Extraction$ClassInstanceBuilder$$buildCtorArg(Extraction.scala:388)
at org.json4s.Extraction$ClassInstanceBuilder$$anonfun$11.apply(Extraction.scala:396)
Is it possible just to let it be null ?
Source: (StackOverflow)
I am experimenting with the json4s library (based on lift-json). One of the things I would like to do is to parse a JSON string into an AST, and then manipulate it.
For example, I would like to upsert a field (insert the field into the AST if it does not exist, or update its value if it does).
I have not been able to find how to do it in the documentation. Experimenting with the available methods, I have come up with the following, which works, but feels clumsy.
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)
}
}
}
I dislike it for many reasons:
- Having to explicitly cast the results of
parse(json)
to JObject
- The result of the
upsertField
function is a JValue
, which I will have to recast if I want to manipulate the object further
- The
upsertField
function just feels very unelegant
- It does not work for fields that are not at the top level of the hierarchy
Is there a better way to transform the AST?
EDIT: as a workaround to the problem, I have managed to convert my JSON to Scala regular classes, and manipulate them with lenses (Using Lenses on Scala Regular Classes)
Source: (StackOverflow)
I'm learning Json4s library.
I have a json fragment like this:
{
"records":[
{
"name":"John Derp",
"address":"Jem Street 21"
},
{
"name":"Scala Jo",
"address":"in my sweet dream"
}
]
}
And, I have Scala code, which converts a json string into a List of Maps, like this:
import org.json4s._
import org.json4s.JsonAST._
import org.json4s.native.JsonParser
val json = JsonParser.parse( """{"records":[{"name":"John Derp","address":"Jem Street 21"},{"name":"Scala Jo","address":"in my sweet dream"}]}""")
val records: List[Map[String, Any]] = for {
JObject(rec) <- json \ "records"
JField("name", JString(name)) <- rec
JField("address", JString(address)) <- rec
} yield Map("name" -> name, "address" -> address)
println(records)
The output of records
to screen gives this:
List(Map(name -> John Derp, address -> Jem Street 21), Map(name ->
Scala Jo, address -> in my sweet dream))
I want to understand what the lines inside the for
loop mean. For example, what is the meaning of this line:
JObject(rec) <- json \ "records"
I understand that the json \ "records"
produces a JArray
object, but why is it fetched as JObject(rec)
at left of <-
? What is the meaning of the JObject(rec)
syntax? Where does the rec
variable come from? Does JObject(rec)
mean instantiating a new JObject
class from rec
input?
BTW, I have a Java programming background, so it would also be helpful if you can show me the Java equivalent code for the loop above.
Source: (StackOverflow)