GithubHelp home page GithubHelp logo

jijo's Introduction

jijo: Bidirectional JSON serialization

Build Status

Design Goals

  • Explicitness – decouple types and encoders/decoders (unlike autoderived instances in Aeson).

  • Bidirectionality – use the same definition for encoding and decoding to prevent mistakes when one side of the definition is updated and the other is not.

  • Completeness – collect as many validation errors as possible, instead of stopping after the first error.

Module Structure

Core:

  • JSON.Definition – the core of the framework, includes combinators for defining complete JSON definitions, parsing primitives, objects, sums, and adding predicates to validate complex conditions.

  • JSON.Validation – the validation machinery, complex enough to deserve its own module.

  • JSON.Path – utilities for working with JSONPath, which is used for error reporting.

Records:

  • RecordField.* – helpers for generating record constructors that make it harder to mix up fields when decoding records from JSON.

An Example

$ stack repl

Encoding:

> uuid <- Data.UUID.V4.nextRandom

> encodeViaDefinition jUUID uuid
String "c7d63bec-517b-48d8-b77a-bc44d05f24af"

Decoding, happy path:

> import Data.Aeson

> validateViaDefinition jUUID (String "c7d63bec-517b-48d8-b77a-bc44d05f24af")
Right c7d63bec-517b-48d8-b77a-bc44d05f24af

Decoding, type mismatch:

> validateViaDefinition jUUID (Number 42)
Left (JValidationReport [JTypeNotOneOf (fromList [JTyString])] (fromList []))

Decoding, malformed UUID:

> validateViaDefinition jUUID (String "invalid")
Left (JValidationReport [JValidationFail InvalidUUID] (fromList []))

The errors are returned as a prefix tree of JValidationErrors indexed by JPathSegment. They can include domain-specific errors.

Implementation Details

JValidation

JValidation is defined as follows:

data JValidation e a =
  JValidation (Maybe a) (JValidationReport e)

data JValidationReport e =
  JValidationReport [JValidationError e] (Map JPathSegment (JValidationReport e))
  • e is the type of domain-specific errors.
  • j is the validation input (for example, JSON.Value)
  • a is the validation result.

The Applicative instance for JValidation accumulates errors from all subcomputations. We don't want to have a Monad instance for JValidation because it would violate the (<*>) = ap law.

JDefinition

JDefinition is a categorical (arrow) product of a validator and an encoder:

type JDefinition e = ArrPair (ValidationArr e) EncodingArr

data ArrPair p q j a = ArrPair (p j a) (q j a)

newtype ValidationArr e j a =
  ValidationArr (j -> JValidation e a)

newtype EncodingArr j a =
  EncodingArr (a -> j)

It has a Category instance that can be used for sequential/monadic validation: any failed step of the pipeline aborts the pipeline. In most cases, a JDefinition can be built by using the same recipe:

  • narrow down the type using one of existing primitive combinators
  • (jString, jObject, etc), parse (probably using jObjectDefinition),
  • then add extra predicates using jDefinition.

JObjectDefinition

JObjectDefinition is an applicative Product of a validator and an encoder. It can be converted into a JDefinition. It does not have a Monad instance but it can be used for "parallel" applicative validation – all errors will be reported in parallel.

makeRecBuilder

jField uses explicit type applications so that fields would not be mixed up; makeRecBuilder wraps constructors into something that takes explicitly named fields.

Future Work

  • Use -XDerivingVia instead of coerce once GHC 8.10 is out (due to three-release policy).

  • Better document how to use sum type validation. There are tests in JSON.DefinitionSpec but no docs yet.

  • TODO: comment on BadExponent.

  • Move the Field machinery into named?

  • Use something like Barbies or higgledy to get rid of Field and move field names into types?

jijo's People

Contributors

int-index avatar neongreen avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

jijo's Issues

Repository status?

Is this repository being worked on internally, or are you accepting open-source contributions?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.