Deadpan-DDP-0.9.4.0: Write clients for Meteor's DDP Protocol

Safe HaskellNone
LanguageHaskell2010

Data.EJson

Description

The DDP protocol uses an extended JSON format called EJSON. This is embedded inside JSON, so that all JSON is valid EJSON, but with certain object structures representing the extended types:

https://github.com/meteor/meteor/blob/devel/packages/ddp/DDP.md

This module provides a pair of functions, value2EJson and ejson2value that convert back and forth between these datatypes. It also provides the EJsonValue datatype itself.

Currently there is no implementation of the usual Aeson conversion classes, but this may change in the future.

There are several smart-constructors made available to construct instances of EJsonValue more easily. These match the constructors exactly, except for substituting lists for vectors, etc... These definitions are inlined.

EJson functionality is intended to be used simply by importing EJson.

The internals of EJson are defined in EJson.

Aeson instances are defined in Aeson.

This module tests examples and properties using DocTest.

Synopsis

Documentation

matches :: EJsonValue -> EJsonValue -> Bool Source

A function to check if all of the values in a match values that exist in b. Not the same as equality.

      { x = L             ==  { x = L
      , y = M     =     ==  , y = M
      , z = N             ==  , z = N
      }                  ...  , a = ... }
  

is still considered as matching.

Matching is applied recursively.

Items that are not EJObjects are compared for equality directly.

getInPath :: [Text] -> EJsonValue -> Maybe EJsonValue Source

getInPath fetches a value from an EJsonValue object at a point indicated by a path.

The path is a list of text values indicating successive object keys.

Examples:

>>> getInPath ["a"] (ejobject [("a","b"),("x","y")])
Just "b"

If you attempt to retrieve a value that does not exist, then you will get Nothing.

Example:

>>> getInPath ["a","q","r"] (ejobject [("x","y")])
Nothing

putInPath :: [Text] -> EJsonValue -> EJsonValue -> Either String EJsonValue Source

putInPath is a method for placing a value into an EJsonValue object at a point indicated by a path The path is a list of text values indicating successive object keys. This can't be done with simple lenses, as the nested obects may not exist. If they do exist, then it is simply an update. However, if they don't exist then EJObjects are created during the traversal.

Examples:

>>> putInPath ["a"] "b" (ejobject [("x","y")])
Right {"a":"b","x":"y"}
>>> putInPath ["a","q","r"] (ejobject [("s","t")]) (ejobject [("x","y")])
Right {"a":{"q":{"r":{"s":"t"}}},"x":"y"}

If you attempt to update a value as if it were an EJObject when in-fact it is something else, then you will receive an Error.

Example:

>>> putInPath ["a", "b"] "c" (ejobject [("a","hello")])
Left "Value \"hello\" does not match path [\"b\"]."

putInPath' :: [Text] -> EJsonValue -> EJsonValue -> EJsonValue Source

A variatnt of putInPath that leaves the EJsonValue unchanged if the update is not sensible

Example:

>>> putInPath' ["a"] "b" "hello"
"hello"

modifyInPath :: [Text] -> EJsonValue -> EJsonValue -> Either String EJsonValue Source

modifyInPath modifies values in an EJsonValue object at a point indicated by a path.

Examples:

>>> modifyInPath [] (ejobject [("q","r")]) (ejobject [("x","y")])
Right {"q":"r","x":"y"}

If you attempt to update a value as if it were an EJObject when in-fact it is something else, then you will receive an Error.

Example:

>>> modifyInPath ["a", "b"] "c" (ejobject [("a","hello")])
Left "Path [\"a\",\"b\"] not present in object {\"a\":\"hello\"}"
>>> modifyInPath ["a", "b"] (ejobject [("a","hello")]) "c"
Left "Path [\"a\",\"b\"] not present in object \"c\""

modifyInPath' :: [Text] -> EJsonValue -> EJsonValue -> EJsonValue Source

A variatnt of modifyInPath that leaves the EJsonValue unchanged if the update is not sensible.

Example:

>>> modifyInPath' ["a", "b"] "c" (ejobject [("a","hello")])
{"a":"hello"}
>>> modifyInPath' ["a", "b"] (ejobject [("a","hello")]) "c"
"c"

removeFromPath :: [Text] -> EJsonValue -> Either String EJsonValue Source

removeFromPath removes values from an EJsonValue object at a point indicated by a path.

The path is a list of text values indicating successive object keys.

Examples:

>>> removeFromPath ["a"] (ejobject [("a","b"),("x","y")])
Right {"x":"y"}

If you attempt to update a value as if it were an EJObject when in-fact it is something else, then you will receive an Error.

Example:

>>> removeFromPath ["a","q","r"] (ejobject [("x","y")])
Left "Path [\"a\",\"q\",\"r\"] not present in object {\"x\":\"y\"}"

removeFromPath' :: [Text] -> EJsonValue -> EJsonValue Source

A variatnt of removeFromPath that leaves the EJsonValue unchanged if the update is not sensible

Example:

>>> removeFromPath' ["a","b"] (ejobject [("a", ejobject [("b","c")]), ("d","e")])
{"a":{},"d":"e"}
>>> removeFromPath' ["a"] "hello"
"hello"

pathToTraversal' :: [Text] -> Traversal' (Maybe EJsonValue) (Maybe EJsonValue) Source

Constructs a Traversal' along a path of EJObject keys.

Both ends of the traversal are maybes in order to allow self-composition, and to allow the insertion/deletion of values at a point in the path.

makeMsg :: Text -> EJsonValue Source

Construct a simple message object with no data.

isEJObject :: EJsonValue -> Bool Source

Examples:

>>> isEJObject EJNull
False

Constructor tests...

isEJArray :: EJsonValue -> Bool Source

Examples:

>>> isEJObject EJNull
False

Constructor tests...

isEJString :: EJsonValue -> Bool Source

Examples:

>>> isEJObject EJNull
False

Constructor tests...

isEJNumber :: EJsonValue -> Bool Source

Examples:

>>> isEJObject EJNull
False

Constructor tests...

isEJBool :: EJsonValue -> Bool Source

Examples:

>>> isEJObject EJNull
False

Constructor tests...

isEJDate :: EJsonValue -> Bool Source

Examples:

>>> isEJObject EJNull
False

Constructor tests...

isEJBinary :: EJsonValue -> Bool Source

Examples:

>>> isEJObject EJNull
False

Constructor tests...

isEJUser :: EJsonValue -> Bool Source

Examples:

>>> isEJObject EJNull
False

Constructor tests...

isEJNull :: EJsonValue -> Bool Source

Examples:

>>> isEJObject EJNull
False

Constructor tests...