Skip to content

circe 0.6.0 #79

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Nov 15, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ resolvers ++= Seq(
)

libraryDependencies ++= {
val circeVersion = "0.5.2"
val circeVersion = "0.6.0"
val akkaVersion = "2.4.8"

Seq(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package org.zalando.jsonapi.json.circe

import cats.data.Xor
import io.circe._
import org.zalando.jsonapi.json.FieldNames
import org.zalando.jsonapi.model.JsonApiObject._
Expand All @@ -20,23 +19,23 @@ trait CirceJsonapiDecoders {
}.toList)
)

implicit val valueDecoder = Decoder.instance[Value](_.as[Json].map(jsonToValue))
implicit val valueDecoder = Decoder.instance[Value](_.as[Json].right.map(jsonToValue))

implicit val attributesDecoder = Decoder.instance[Attributes](hcursor ⇒ {
hcursor.as[Value].flatMap {
hcursor.as[Value].right.flatMap {
case JsObjectValue(value) ⇒
Xor.Right(value)
Right(value)
case _ ⇒
Xor.Left(DecodingFailure("only an object can be decoded to Attributes", hcursor.history))
Left(DecodingFailure("only an object can be decoded to Attributes", hcursor.history))
}
})

implicit val attributeDecoder = Decoder.instance[Attribute](_.as[Attributes].map(_.head))
implicit val attributeDecoder = Decoder.instance[Attribute](_.as[Attributes].right.map(_.head))

implicit val linksDecoder = Decoder.instance[Links](hcursor ⇒ {
hcursor.as[Value].flatMap {
hcursor.as[Value].right.flatMap {
case JsObjectValue(attributes) ⇒
Xor.Right(attributes.map {
Right(attributes.map {
case Attribute(FieldNames.`self`, StringValue(url)) ⇒ Links.Self(url)
case Attribute(FieldNames.`about`, StringValue(url)) ⇒
Links.About(url)
Expand All @@ -49,22 +48,23 @@ trait CirceJsonapiDecoders {
Links.Related(url)
})
case _ ⇒
Xor.Left(DecodingFailure("only an object can be decoded to Links", hcursor.history))
Left(DecodingFailure("only an object can be decoded to Links", hcursor.history))
}
})

def jsonToData(json: Json): Xor[DecodingFailure, Data] = json match {
def jsonToData(json: Json): Either[DecodingFailure, Data] = json match {
case json: Json if json.isArray ⇒
json.as[ResourceObjects]
case json: Json if json.isObject ⇒
json.as[ResourceObject]
}

implicit val dataDecoder = Decoder.instance[Data](_.as[Json].right.flatMap(jsonToData))

implicit val relationshipDecoder = Decoder.instance[Relationship](hcursor ⇒ {
for {
links ← hcursor.downField(FieldNames.`links`).as[Option[Links]]
// TODO: there's prolly a cleaner way here. there's a circular dependency Data -> ResourceObject(s) -> Relationship(s) -> Data that's giving circe problems
data ← hcursor.downField(FieldNames.`data`).as[Option[Json]].map(_.flatMap(jsonToData(_).toOption))
links ← hcursor.downField(FieldNames.`links`).as[Option[Links]].right
data ← hcursor.downField(FieldNames.`data`).as[Option[Data]].right
} yield
Relationship(
links = links,
Expand All @@ -75,31 +75,31 @@ trait CirceJsonapiDecoders {
implicit val relationshipsDecoder = Decoder.instance[Relationships](_.as[Map[String, Relationship]])

implicit val jsonApiDecoder = Decoder.instance[JsonApi](hcursor ⇒ {
hcursor.as[Value].flatMap {
hcursor.as[Value].right.flatMap {
case JsObjectValue(attributes) ⇒
Xor.Right(attributes.map {
Right(attributes.map {
case Attribute(name, value) ⇒ JsonApiProperty(name, value)
})
case _ ⇒
Xor.Left(DecodingFailure("only an object can be decoded to JsonApi", hcursor.history))
Left(DecodingFailure("only an object can be decoded to JsonApi", hcursor.history))
}
})

implicit val metaDecoder = Decoder.instance[Meta](hcursor ⇒ {
hcursor.as[Value].flatMap {
hcursor.as[Value].right.flatMap {
case JsObjectValue(attributes) ⇒
Xor.Right(attributes.map {
Right(attributes.map {
case Attribute(name, value) ⇒ name -> value
}.toMap)
case _ ⇒
Xor.Left(DecodingFailure("only an object can be decoded to Meta", hcursor.history))
Left(DecodingFailure("only an object can be decoded to Meta", hcursor.history))
}
})

implicit val errorSourceDecoder = Decoder.instance[ErrorSource](hcursor ⇒ {
for {
pointer ← hcursor.downField(FieldNames.`pointer`).as[Option[String]]
parameter ← hcursor.downField(FieldNames.`parameter`).as[Option[String]]
pointer ← hcursor.downField(FieldNames.`pointer`).as[Option[String]].right
parameter ← hcursor.downField(FieldNames.`parameter`).as[Option[String]].right
} yield
ErrorSource(
pointer = pointer,
Expand All @@ -109,14 +109,14 @@ trait CirceJsonapiDecoders {

implicit val errorDecoder = Decoder.instance[Error](hcursor ⇒ {
for {
id ← hcursor.downField(FieldNames.`id`).as[Option[String]]
status ← hcursor.downField(FieldNames.`status`).as[Option[String]]
code ← hcursor.downField(FieldNames.`code`).as[Option[String]]
title ← hcursor.downField(FieldNames.`title`).as[Option[String]]
detail ← hcursor.downField(FieldNames.`detail`).as[Option[String]]
links ← hcursor.downField(FieldNames.`links`).as[Option[Links]]
meta ← hcursor.downField(FieldNames.`meta`).as[Option[Meta]]
source ← hcursor.downField(FieldNames.`source`).as[Option[ErrorSource]]
id ← hcursor.downField(FieldNames.`id`).as[Option[String]].right
status ← hcursor.downField(FieldNames.`status`).as[Option[String]].right
code ← hcursor.downField(FieldNames.`code`).as[Option[String]].right
title ← hcursor.downField(FieldNames.`title`).as[Option[String]].right
detail ← hcursor.downField(FieldNames.`detail`).as[Option[String]].right
links ← hcursor.downField(FieldNames.`links`).as[Option[Links]].right
meta ← hcursor.downField(FieldNames.`meta`).as[Option[Meta]].right
source ← hcursor.downField(FieldNames.`source`).as[Option[ErrorSource]].right
} yield
Error(
id = id,
Expand All @@ -132,12 +132,12 @@ trait CirceJsonapiDecoders {

implicit val resourceObjectDecoder = Decoder.instance[ResourceObject](hcursor ⇒ {
for {
id ← hcursor.downField(FieldNames.`id`).as[Option[String]]
`type` ← hcursor.downField(FieldNames.`type`).as[String]
attributes ← hcursor.downField(FieldNames.`attributes`).as[Option[Attributes]]
relationships ← hcursor.downField(FieldNames.`relationships`).as[Option[Relationships]]
links ← hcursor.downField(FieldNames.`links`).as[Option[Links]]
meta ← hcursor.downField(FieldNames.`meta`).as[Option[Meta]]
id ← hcursor.downField(FieldNames.`id`).as[Option[String]].right
`type` ← hcursor.downField(FieldNames.`type`).as[String].right
attributes ← hcursor.downField(FieldNames.`attributes`).as[Option[Attributes]].right
relationships ← hcursor.downField(FieldNames.`relationships`).as[Option[Relationships]].right
links ← hcursor.downField(FieldNames.`links`).as[Option[Links]].right
meta ← hcursor.downField(FieldNames.`meta`).as[Option[Meta]].right
} yield
ResourceObject(
id = id,
Expand All @@ -150,20 +150,18 @@ trait CirceJsonapiDecoders {
})

implicit val resourceObjectsDecoder =
Decoder.instance[ResourceObjects](_.as[List[ResourceObject]].map(ResourceObjects))

implicit val dataDecoder = Decoder.instance[Data](_.as[Json].flatMap(jsonToData))
Decoder.instance[ResourceObjects](_.as[List[ResourceObject]].right.map(ResourceObjects))

implicit val includedDecoder = Decoder.instance[Included](_.as[ResourceObjects].map(Included.apply))
implicit val includedDecoder = Decoder.instance[Included](_.as[ResourceObjects].right.map(Included.apply))

implicit val rootObjectDecoder = Decoder.instance[RootObject](hcursor ⇒ {
for {
data ← hcursor.downField(FieldNames.`data`).as[Option[Data]]
links ← hcursor.downField(FieldNames.`links`).as[Option[Links]]
errors ← hcursor.downField(FieldNames.`errors`).as[Option[Errors]]
meta ← hcursor.downField(FieldNames.`meta`).as[Option[Meta]]
included ← hcursor.downField(FieldNames.`included`).as[Option[Included]]
jsonapi ← hcursor.downField(FieldNames.`jsonapi`).as[Option[JsonApi]]
data ← hcursor.downField(FieldNames.`data`).as[Option[Data]].right
links ← hcursor.downField(FieldNames.`links`).as[Option[Links]].right
errors ← hcursor.downField(FieldNames.`errors`).as[Option[Errors]].right
meta ← hcursor.downField(FieldNames.`meta`).as[Option[Meta]].right
included ← hcursor.downField(FieldNames.`included`).as[Option[Included]].right
jsonapi ← hcursor.downField(FieldNames.`jsonapi`).as[Option[JsonApi]].right
} yield
RootObject(
data = data,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ trait CirceJsonapiSupport extends CirceJsonapiEncoders with CirceJsonapiDecoders
implicit val circeJsonapiUnmarshaller = Unmarshaller.delegate[String, RootObject](
`application/vnd.api+json`,
`application/json`
)(decode[RootObject](_).toOption.get)
)(decode[RootObject](_).right.get)
}

object CirceJsonapiSupport extends CirceJsonapiSupport
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ import org.zalando.jsonapi.model._

class CirceJsonapiFormatSpec extends JsonBaseSpec[Json] with MustMatchers with CirceJsonapiEncoders with CirceJsonapiDecoders {

override protected def parseJson(jsonString: String): Json = parse(jsonString).toOption.get
protected def decodeJson[T](json: Json)(implicit d: io.circe.Decoder[T]): T = json.as[T].toOption.get
override protected def parseJson(jsonString: String): Json = parse(jsonString).right.get
protected def decodeJson[T](json: Json)(implicit d: io.circe.Decoder[T]): T = json.as[T].right.get

"CirceJsonapiFormat" when {
"serializing Jsonapi" must {
Expand Down
2 changes: 1 addition & 1 deletion version.sbt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
version in ThisBuild := "0.5.4"
version in ThisBuild := "0.6.0"