spartanz / schemaz

A purely-functional library for defining type-safe schemas for algebraic data types, providing free generators, SQL queries, JSON codecs, binary codecs, and migration from this schema definition
https://spartanz.github.io/schemaz
Apache License 2.0
164 stars 18 forks source link

JSON (proper) #32

Open vil1 opened 5 years ago

vil1 commented 5 years ago

We currently have a toy example interpreting schemas into JSON encoders, that merely stands as an example/POC for interpreting schemas into contravariant functors.

We need to add modules for working real-world JSON libraries (prioritising the most widely used).

Candidates are:

GrafBlutwurst commented 5 years ago

One current issue is that it is quite trivial to derive an encoder which will generate invalid JSON.

val tplSchema: Fix[Schema, (Boolean, String)] = prim(JsonSchema.JsonBool) :*: prim(JsonSchema.JsonString)

        implicit val primToEncoderNT = new (Prim ~> Encoder) {
          def apply[A](fa: Prim[A]): Encoder[A] = { a =>
            fa match {
              case JsonNumber => a.toString
              case JsonBool   => a.toString
              case JsonString => s""""$a""""
              case JsonNull   => "null"
            }
          }
        }

        val serializer: Encoder[(Boolean, String)] = tplSchema.to[Encoder]
        val out = serializer((true, "asdf"))
        Fail.string(out)

will output true, "asdf"

the problem here is that there is no "sensible" encoder for an anonymous tuple. So far I see 2 possibilities to rectify this:

1) introduce default values for such cases 2) add errors to the derivation Error \/ Encoder[A] and return an error if the derivation is for a schema that has no sensible json encoder.

both of there would require a more powerful fold than cata probably histo so we can inspect the structure of the already folded part in the :*: case to determine whether the underlying terms are labelled or not.

sasiharan commented 5 years ago

@vil1 I would like to work on schema module for Circe library if you have not started on it.