{"id":16485404,"url":"https://github.com/zaid-ajaj/fable.simplejson","last_synced_at":"2025-03-16T18:31:45.239Z","repository":{"id":27992909,"uuid":"115811760","full_name":"Zaid-Ajaj/Fable.SimpleJson","owner":"Zaid-Ajaj","description":"A library for working with JSON in Fable projects ","archived":false,"fork":false,"pushed_at":"2023-01-01T19:34:58.000Z","size":1305,"stargazers_count":59,"open_issues_count":3,"forks_count":17,"subscribers_count":5,"default_branch":"master","last_synced_at":"2025-02-27T12:14:51.957Z","etag":null,"topics":["fable","json","parser"],"latest_commit_sha":null,"homepage":"","language":"F#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Zaid-Ajaj.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-12-30T17:23:12.000Z","updated_at":"2024-08-20T02:41:31.000Z","dependencies_parsed_at":"2023-01-14T07:53:38.148Z","dependency_job_id":null,"html_url":"https://github.com/Zaid-Ajaj/Fable.SimpleJson","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Zaid-Ajaj%2FFable.SimpleJson","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Zaid-Ajaj%2FFable.SimpleJson/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Zaid-Ajaj%2FFable.SimpleJson/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Zaid-Ajaj%2FFable.SimpleJson/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Zaid-Ajaj","download_url":"https://codeload.github.com/Zaid-Ajaj/Fable.SimpleJson/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243826783,"owners_count":20354220,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["fable","json","parser"],"created_at":"2024-10-11T13:25:48.604Z","updated_at":"2025-03-16T18:31:44.672Z","avatar_url":"https://github.com/Zaid-Ajaj.png","language":"F#","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Fable.SimpleJson [![Build Status](https://travis-ci.org/Zaid-Ajaj/Fable.SimpleJson.svg?branch=master)](https://travis-ci.org/Zaid-Ajaj/Fable.SimpleJson) [![Build status](https://ci.appveyor.com/api/projects/status/i17usjpn7bbiwm9n?svg=true)](https://ci.appveyor.com/project/Zaid-Ajaj/fable-simplejson) [![Nuget](https://img.shields.io/nuget/v/Fable.SimpleJson.svg?maxAge=0\u0026colorB=brightgreen)](https://www.nuget.org/packages/Fable.SimpleJson)\n\nA simple library for easily parsing, transforming and converting JSON in Fable projects. It is written using parser combinators from [Fable.Parsimmon](https://github.com/Zaid-Ajaj/Fable.Parsimmon)\n\n### Installation\n\nInstall from nuget using dotnet:\n\n```sh\ndotnet add package Fable.SimpleJson\n```\n\nInstall from nuget using paket\n\n```sh\npaket add nuget Fable.SimpleJson --project path/to/YourProject.fsproj\n```\n\nMake sure the references are added to your paket files\n\n```sh\n# paket.dependencies (solution-wide dependencies)\nnuget Fable.SimpleJson\n\n# paket.references (project-specific dependencies)\nFable.SimpleJson\n```\n\n## Raison d'être\n\nFable.SimpleJson allows for generic JSON data manipulation and treats JSON as a [data structure](https://github.com/Zaid-Ajaj/Fable.SimpleJson/blob/master/src/Json.fs) 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](https://www.newtonsoft.com/json/help/html/CreateJsonManually.htm) API from Newtonsoft.Json)\n\nThe 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](https://github.com/MangelMaxime/Thoth)).\n\nBecause of the flexibility it provides, it forms a solid foundation for JSON handling in [Fable.Remoting](https://github.com/Zaid-Ajaj/Fable.Remoting), [Elmish.Bridge](https://github.com/Nhowka/Elmish.Bridge) and [Fable.SignalR](https://github.com/Shmew/Fable.SignalR).\n\n### Using the library\n\nJSON Parsing and Transformation API\n```fs\nopen Fable.SimpleJson\n\n// ...\n\nSimpleJson.tryParse : string -\u003e Option\u003cJson\u003e\nSimpleJson.parse : string -\u003e Json\nSimpleJson.toString : Json -\u003e string\nSimpleJson.fromObjectLiteral : 'a -\u003e Option\u003cJson\u003e\nSimpleJson.mapKeys : (f: string -\u003e string) -\u003e Json -\u003e Json\nSimpleJson.mapKeysByPath : (f: string list -\u003e string option) -\u003e Json -\u003e Json\n```\nJSON Convertion API\n```fs\nopen Fable.SimpleJson\n\n// Parsing from JSON\n\nJson.parseAs\u003c't\u003e (inputJson: string) : 't\nJson.tryParseAs\u003c't\u003e (inputJson: string) : Result\u003c't, string\u003e\nJson.parseFromJsonAs\u003c't\u003e (parsedJson: Json) : 't\nJson.tryParseFromJsonAs\u003c't\u003e (parsedJson: Json) : Result\u003c't, string\u003e\n\n// Converting to JSON\n\nJson.stringify(value: obj) : string // Use for Fable 2.x applications\nJson.serialize\u003c't\u003e(value: 't) : string // Supports Fable 2.x and Fable 3\n```\n\nThe AST looks like this:\n```fs\ntype Json =\n    | JNumber of float\n    | JString of string\n    | JBool of bool\n    | JNull\n    | JArray of Json list\n    | JObject of Map\u003cstring, Json\u003e\n```\n\n## Auto Deserialization\nSuppose you have the record of `Person`, you can then use `Json.parseAs\u003c't\u003e` for automatic deserialization:\n```fs\ntype Person = { Name: string; Age: int }\n\n\"{ \\\"Name\\\": \\\"John\\\", \\\"Age\\\": 42  }\"\n|\u003e Json.parseAs\u003cPerson\u003e\n// result =\u003e { Name = \"John\"; Age = 42 }\n```\n\n## Manual Deserialization\nSuppose you have the record of `Person`:\n```fs\ntype Person = { Name: string; Age: int }\n```\nAnd you want to deserialize this string:\n```json\n\"{ \\\"name\\\":\\\"john\\\", \\\"age\\\":20 }\"\n```\nThen you can would use the safe `SimpleJson.tryParse` to pattern-match and extract the values from the parsed JSON:\n```fs\nopen Fable.SimpleJson\n\n\"{ \\\"name\\\":\\\"john\\\", \\\"age\\\":20 }\"\n|\u003e SimpleJson.tryParse\n|\u003e function\n    | Some (JObject dict) -\u003e\n        let value key = Map.tryFind key dict\n        [value \"name\"; value \"age\"]\n        |\u003e List.choose id\n        |\u003e function\n            | [JString name; JNumber age]  -\u003e\n                Some { Name = name; Age = int age }\n            | _ -\u003e None\n    | _ -\u003e None\n```\nYou 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.\n\n## Auto Serialization\n\n```fs\nlet person = { Name = \"John\"; Age = 34 }\nJson.serialize person\n```\n\n## Manual Serialization\n\nNow, to serialize a typed entity into a JSON string there are two ways:\n\n1. You build the JSON structure by hand and call `SimpleJson.toString` like the following:\n\n```fs\nlet person = { Name = \"John\"; Age = 34 }\n\nlet serialized =\n    [ \"name\", JString person.Name\n      \"age\", JNumber (float person.Age) ]\n    |\u003e Map.ofList\n    |\u003e JObject\n    |\u003e SimpleJson.toString\n```\n\nor\n\n2. You use anonymous records and call `Json.serialize` like the following:\n\n```fs\nlet person = { Name = \"John\"; Age = 34 }\n\nlet serialized = Json.serialize {| name = person.Name ; age = person.Age |}\n```\n\nThere is a big difference here because using a `Map -\u003e JObject` means that you can dynamically add or remove properties at runtime where as an anonymous record will have a static shape. Both ways are valid, though the first example is lower-level and most people will probably need the second one with anonymous records.\n\n## Pre-processing JSON values\nSuppose you want to deserialize the string:\n\n```json\n{  \"first_name\": \"John\",\n   \"last_name\": \"Doe\"    }\n```\nAnd you have the type\n```fs\ntype Person = { FirstName: string; LastName: string }\n```\nThen 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:\n```fs\n\"{\\\"first_name\\\":\\\"John\\\",\\\"last_name\\\":\\\"Doe\\\"}\"\n|\u003e SimpleJson.parse\n|\u003e SimpleJson.mapKeys (function\n    | \"first_name\" -\u003e \"FirstName\"\n    | \"last_name\" -\u003e \"LastName\"\n    | key -\u003e key)\n|\u003e Json.convertFromJsonAs\u003cPerson\u003e\n // { FirstName = \"John\"; LastName = \"Doe\" }\n```\n\n# Selective re-writing of JSON keys based on key path:\nThe 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`:\n\n```fs\ntestCase \"mapKeysByPath works\" \u003c| fun test -\u003e\n    \"[{\\\"person\\\":{\\\"first\\\":\\\"john\\\", \\\"last\\\":\\\"doe\\\"}}, {\\\"first\\\":\\\"not-mapped\\\"}]\"\n    |\u003e SimpleJson.parse\n    |\u003e SimpleJson.mapKeysByPath (function\n        | [\"person\"] -\u003e Some \"Person\"\n        | [\"person\";\"first\"] -\u003e Some \"first_name\"\n        | [\"person\";\"last\"] -\u003e Some \"last_name\"\n        | other -\u003e None)\n    |\u003e SimpleJson.toString\n    |\u003e test.areEqual \"[{\\\"Person\\\":{\\\"first_name\\\":\\\"john\\\",\\\"last_name\\\":\\\"doe\\\"}},{\\\"first\\\":\\\"not-mapped\\\"}]\"\n```\n## Building and running tests\nRequirements\n\n - Dotnet 2.2+\n - Node.js 10.0+\n\n\nRunning and watching the tests live in the browser:\n```sh\nnpm install\nnpm start\n```\nWhen the development server starts, navigate to `http://localhost:8080` to see the test results.\n\nBuilding the tests and running them using Mocha on Node.js\n```sh\nnpm install\nnpm test\n```\nThis will compile the project using `fable-splitter` and run mocha against the generated files in `dist`.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzaid-ajaj%2Ffable.simplejson","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fzaid-ajaj%2Ffable.simplejson","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzaid-ajaj%2Ffable.simplejson/lists"}