Parsing a simple array using Spray-json

I try (and cannot) figure out how spray json turns json into objects. If I have a simple key -> json feed value, then it works fine, but the data I want to read is on a list like this:

[{ "name": "John", "age": "30" }, { "name": "Tom", "age": "25" }] 

And my code looks like this:

 package jsontest import spray.json._ import DefaultJsonProtocol._ object JsonFun { case class Person(name: String, age: String) case class FriendList(items: List[Person]) object FriendsProtocol extends DefaultJsonProtocol { implicit val personFormat = jsonFormat2(Person) implicit val friendListFormat = jsonFormat1(FriendList) } def main(args: Array[String]): Unit = { import FriendsProtocol._ val input = scala.io.Source.fromFile("test.json")("UTF-8").mkString.parseJson val friendList = input.convertTo[FriendList] println(friendList) } } 

If I modify my test file so that it just has one person not in the array and run val friendList = input.convertTo[Person] , then it will work and everything will be analyzed, but as soon as I try and analyze the array, it suffers failed with error Object expected in field 'items'

Can someone point me in the direction of what I am doing wrong?

+6
source share
2 answers

Well, as it often happens right after publishing something on StackOverflow, after spending hours working on something, I managed to get it working.

The correct implementation of FriendsProtocol:

 object FriendsProtocol extends DefaultJsonProtocol { implicit val personFormat = jsonFormat2(Person) implicit object friendListJsonFormat extends RootJsonFormat[FriendList] { def read(value: JsValue) = FriendList(value.convertTo[List[Person]]) def write(f: FriendList) = ??? } } 

Tell me how to read or write (just read in my case) that the list object is enough to make it work.

Hope this helps someone else!

+8
source

To simplify the use of the Friend array, extend the IndexedSeq [Person] property by following the appropriate application methods and lengths. This will allow standard Scala Collections API methods, such as map, filter, and sortBy, directly on the FriendsArray instance, without the need to access the base [Person] array that it wraps.

 case class Person(name: String, age: String) // this case class allows special sequence trait in FriendArray class // this will allow you to use .map .filter etc on FriendArray case class FriendArray(items: Array[Person]) extends IndexedSeq[Person] { def apply(index: Int) = items(index) def length = items.length } object FriendsProtocol extends DefaultJsonProtocol { implicit val personFormat = jsonFormat2(Person) implicit object friendListJsonFormat extends RootJsonFormat[FriendArray] { def read(value: JsValue) = FriendArray(value.convertTo[Array[Person]]) def write(f: FriendArray) = ??? } } import FriendsProtocol._ val input = jsonString.parseJson val friends = input.convertTo[FriendArray] friends.map(x => println(x.name)) println(friends.length) 

Then it will print:

 John Tom 2 
+2
source

Source: https://habr.com/ru/post/982526/


All Articles