v0.5.0
-
A lot of performance improvements across the whole library
-
Added basic subscription support as defined in the spec (graphql/graphql-spec#109) and reference implementation (#89).
At the moment subscriptions are pretty basic, so it's meant more for experiments rather than for use in real applications.
It is very likely that this feature will experience breaking changes in the near future (spec change) -
Much better handling of input objects (#37, #70). A new type-class is introduced:
FromInput
. It provides high-level and low-level
way to deserialize arbitrary input objects, just likeToInput
.In order to use this feature, you need to provide a type parameter to the
InputObjectType
:case class Article(title: String, text: Option[String]) val ArticleType = InputObjectType[Article]("Article", List( InputField("title", StringType), InputField("text", OptionInputType(StringType)))) val arg = Argument("article", ArticleType)
This code will not compile unless you define an implicit instance of
FromInput
forArticle
case class:implicit val manual = new FromInput[Article] { val marshaller = CoercedScalaResultMarshaller.default def fromResult(node: marshaller.Node) = { val ad = node.asInstanceOf[Map[String, Any]] Article( title = ad("title").asInstanceOf[String], text = ad.get("text").flatMap(_.asInstanceOf[Option[String]]) } }
As you can see, you need to provide a
ResultMarshaller
for desired format and then use a marshaled value to create a domain object based on it.
Many instances ofFromInput
are already provided out-of-the-box. For instanceFromInput[Map[String, Any]]
was added to support existing map-like
data-structure format. All supported Json libraries also provideFromInput[JsValue]
so that you can use Json AST instead of working withMap[String, Any]
.Moreover, play-json and spray-json integration provide support for
Reads
andJsonFormat
. This means that your domain objects are automatically
supported as long as you haveReads
orJsonFormat
defined for them. For instance this example should compile and work just fine without explicit
FromInput
declaration:import sangria.integration.playJson._ import play.api.libs.json._ case class Article(title: String, text: Option[String]) implicit val articleFormat = Json.format[Article] val ArticleType = InputObjectType[Article]("Article", List( InputField("title", StringType), InputField("text", OptionInputType(StringType)))) val arg = Argument("article", ArticleType)
CAUTION: this is minor breaking change. Together with
null
value support, this feature changes the way input objects are
deserialized into map-like structures (which still happens by default). Optional input fields will now produce input
objects like:// for JSON input: {"op1": "foo", "opt2": null} Map("opt1" → Some("foo"), "opt2" → None) // for JSON input: {"op1": "foo"} Map("opt1" → Some("foo"))
instead of (old format):
// for JSON input: {"op1": "foo", "opt2": null} Map("opt1" → "foo") // for JSON input: {"op1": "foo"} Map("opt1" → "foo")
As you can see, this allows you to distinguish between "undefined" json object fields and json object fields that are set to
null
. -
null
value support (as defined in the spec change: graphql/graphql-spec#83) (#55) (spec change) -
Extracted input value parsing and made it a first-class citizen (#103). So now you can parse and render any
ast.Value
independently from
GraphQL query. There is even a newgraphqlInput
macros available:import sangria.renderer.QueryRenderer import sangria.macros._ import sangria.ast val parsed: ast.Value = graphqlInput""" { id: "1234345" version: 2 # changed 2 times deliveries: [ {id: 123, received: false, note: null, state: OPEN} ] } """ val rendered: String = QueryRenderer.render(parsed, QueryRenderer.PrettyInput) println(rendered)
It will print something like this:
{ id: "1234345" version: 2 deliveries: [{ id: 123 received: false note: null state: OPEN }] }
InputUnmarshaller
andResultMarshaller
are also now available for it, so you can useast.Value
as a variables or it can be a result
of GraphQL query execution (instead of more traditional JSON). -
ToInput
,InputUnmarshaller
andResultMarshaller
are moved tosangria.marshalling
package. -
Improved error messages for input values (#86). Now they will contain the reason why particular value is invalid.
-
Implementations of interfaces can include additional field args (#90) (spec change)
-
Loosen overlapping field validation rules (#94) (spec change)
-
False positive validation error from fragment cycle when unknown fragment (#95)
-
Interfaces with covariant return types (#96)
-
A lot of minor changes and performance improvements in validation rules and query validator (#97) (spec change)
-
Add error handling in the
SchemaRenderer
(#100) -
Ambiguous implicit when using a
UnionType
bug (#101) -
A lot of internal refactorings (especially in variable and argument processing) to make everything above possible