GithubHelp home page GithubHelp logo

pkese / fable.simplejson Goto Github PK

View Code? Open in Web Editor NEW

This project forked from zaid-ajaj/fable.simplejson

0.0 1.0 0.0 726 KB

A library for easily parsing and transforming JSON in Fable projects

License: MIT License

F# 98.43% Shell 0.61% HTML 0.11% JavaScript 0.70% Batchfile 0.15%

fable.simplejson's Introduction

Fable.SimpleJson Build Status Build status Nuget

A simple library for easily parsing, transforming and converting JSON in Fable projects. It is written using parser combinators from Fable.Parsimmon

Installation

Install from nuget using paket

paket add nuget Fable.SimpleJson --project path/to/YourProject.fsproj 

Make sure the references are added to your paket files

# paket.dependencies (solution-wide dependencies)
nuget Fable.SimpleJson

# paket.refernces (project-specific dependencies)
Fable.SimpleJson

Raison d'être

Fable.SimpleJson allows for generic JSON data maniplution and treats JSON as a data structure like List or Map. Manipulating JSON as data means that you can use low-level API's to transform and convert JSON from one structure into another or extracting values from the JSON without defining intermediate types (similar to the JToken API from Newtonsoft.Json)

The automatic serialization and deserialization to typed entities happen to be utility functions, one use case, but are not the main purpose of the library (as in with Thoth.Json).

Because of the flexibility it provides, it forms a solid foundation for JSON handling in Fable.Remoting.

Using the library

JSON Parsing and Transformation API

open Fable.SimpleJson 

// ... 

SimpleJson.tryParse : string -> Option<Json>
SimpleJson.parse : string -> Json
SimpleJson.toString : Json -> string
SimpleJson.fromObjectLiteral : 'a -> Option<Json>
SimpleJson.mapKeys : (f: string -> string) -> Json -> Json
SimpleJson.mapKeysByPath : (f: string list -> string option) -> Json -> Json

JSON Convertion API

open Fable.SimpleJson 

// ...

Json.parseAs<'t> (inputJson: string) : 't 
Json.tryParseAs<'t> (inputJson: string) : Result<'t, string> 
Json.parseFromJsonAs<'t> (parsedJson: Json) : 't 
Json.tryParseFromJsonAs<'t> (parsedJson: Json) : Result<'t, string> 

The AST looks like this:

type Json = 
    | JNumber of float
    | JString of string
    | JBool of bool
    | JNull
    | JArray of Json list
    | JObject of Map<string, Json>

Auto Deserialization

Suppose you have the record of Person, you can then use Json.parseAs<'t> for automatic deserialization:

type Person = { Name: string; Age: int }

"{ \"Name\": \"John\", \"Age\": 42  }"
|> Json.parseAs<Person> 
// result => { Name = "John"; Age = 42 }

Manual Deserialization

Suppose you have the record of Person:

type Person = { Name: string; Age: int }

And you want to deserialize this string:

"{ \"name\":\"john\", \"age\":20 }"

Then you can would use the safe SimpleJson.tryParse to pattern-match and extract the values from the parsed JSON:

open Fable.SimpleJson

"{ \"name\":\"john\", \"age\":20 }"
|> SimpleJson.tryParse
|> function
    | Some (JObject dict) ->
        let value key = Map.tryFind key dict
        [value "name"; value "age"]
        |> List.choose id
        |> function
            | [JString name; JNumber age]  -> 
                Some { Name = name; Age = int age }
            | _ -> None
    | _ -> None

You could also use the non-safe version SimpleJson.parse if you know for sure that the JSON input string is parsable. SimpleJson.parse will throw an exception if it can't deserialize the JSON string.

Auto Serialization

let person = { Name = "John"; Age = 34 } 
Json.stringify person 

Manual Serialization

Now, to serialize a typed entity into a JSON string, you build the JSON structure by hand and call SimpleJson.toString like the following:

let person = { Name = "John"; Age = 34 }

let serialized = 
    [ "name", JString person.Name
      "age", JNumber (float person.Age) ]
    |> Map.ofList
    |> JObject
    |> SimpleJson.toString

Pre-processing JSON values

Suppose you want to deserialize the string:

{  "first_name": "John", 
   "last_name": "Doe"    }

And you have the type

type Person = { FirstName: string; LastName: string }

Then obviously it wouldn't "just work" because the keys of the object don't match. SimpleJson can help with this by first rewriting the keys to match with the field names of the record before converting:

"{\"first_name\":\"John\",\"last_name\":\"Doe\"}"
|> SimpleJson.parse
|> SimpleJson.mapKeys (function
    | "first_name" -> "FirstName"
    | "last_name" -> "LastName"
    | key -> key)
|> Json.convertFromJsonAs<Person>
 // { FirstName = "John"; LastName = "Doe" }

Selective re-writing of JSON keys based on key path:

The function SimpleJson.mapKeys will convert every possible key in every object within the JSON structure. Sometimes you want to select exactly which keys to convert based on their path in the JSON using SimpleJson.mapKeysByPath:

testCase "mapKeysByPath works" <| fun test ->
    "[{\"person\":{\"first\":\"john\", \"last\":\"doe\"}}, {\"first\":\"not-mapped\"}]"
    |> SimpleJson.parse
    |> SimpleJson.mapKeysByPath (function
        | ["person"] -> Some "Person"
        | ["person";"first"] -> Some "first_name"
        | ["person";"last"] -> Some "last_name"
        | other -> None)
    |> SimpleJson.toString
    |> test.areEqual "[{\"Person\":{\"first_name\":\"john\",\"last_name\":\"doe\"}},{\"first\":\"not-mapped\"}]"

Building and running tests

Requirements

  • Dotnet 2.2+
  • Node.js 10.0+

Running and watching the tests live in the browser:

npm install
npm start

When the development server starts, navigate to http://localhost:8080 to see the test results.

Building the tests and running them using Mocha on Node.js

npm install
npm test

This will compile the project using fable-splitter and run mocha against the generated files in dist.

fable.simplejson's People

Contributors

0x53a avatar alfonsogarciacaro avatar elonon avatar irium avatar kerams avatar pkese avatar thecentury avatar theimowski avatar zaid-ajaj avatar

Watchers

 avatar

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.