soundtrackyourbrand / Forma

Licence: mit
Typespec based parsing of JSON-like data for Elixir

Programming Languages

elixir
2628 projects

Projects that are alternatives of or similar to Forma

Serpent
A protocol to serialize Swift structs and classes for encoding and decoding.
Stars: ✭ 281 (+1121.74%)
Mutual labels:  json, parsing
Gabs
For parsing, creating and editing unknown or dynamic JSON in Go
Stars: ✭ 2,573 (+11086.96%)
Mutual labels:  json, parsing
Lazyjson
A very fast, very lazy JSON parser for Java.
Stars: ✭ 55 (+139.13%)
Mutual labels:  json, parsing
Jikan
Unofficial MyAnimeList PHP+REST API which provides functions other than the official API
Stars: ✭ 531 (+2208.7%)
Mutual labels:  json, parsing
Jkt
Simple helper to parse JSON based on independent schema
Stars: ✭ 22 (-4.35%)
Mutual labels:  json, parsing
Json.h
🗄️ single header json parser for C and C++
Stars: ✭ 387 (+1582.61%)
Mutual labels:  json, parsing
Staticjson
Fast, direct and static typed parsing of JSON with C++
Stars: ✭ 177 (+669.57%)
Mutual labels:  json, parsing
Sbjson
This framework implements a strict JSON parser and generator in Objective-C.
Stars: ✭ 3,776 (+16317.39%)
Mutual labels:  json, parsing
Jsoniter Scala
Scala macros for compile-time generation of safe and ultra-fast JSON codecs
Stars: ✭ 410 (+1682.61%)
Mutual labels:  json, parsing
Ason
[DEPRECATED]: Prefer Moshi, Jackson, Gson, or LoganSquare
Stars: ✭ 777 (+3278.26%)
Mutual labels:  json, parsing
Acf 5 Pro Json Storage
Save ACF 5 Pro field groups as JSON within this plugin, rather than inside your theme.
Stars: ✭ 16 (-30.43%)
Mutual labels:  json
Json Chunks
streamable json encoder
Stars: ✭ 17 (-26.09%)
Mutual labels:  json
Defiant.js
http://defiantjs.com
Stars: ✭ 907 (+3843.48%)
Mutual labels:  json
Config Rs
⚙️ Layered configuration system for Rust applications (with strong support for 12-factor applications).
Stars: ✭ 915 (+3878.26%)
Mutual labels:  json
Csharpjson
C# 编写的通用Json数据解析库
Stars: ✭ 16 (-30.43%)
Mutual labels:  json
Sanest
sane nested dictionaries and lists for python
Stars: ✭ 19 (-17.39%)
Mutual labels:  json
Json to dart
Library that generates dart classes from json strings
Stars: ✭ 836 (+3534.78%)
Mutual labels:  json
Rust Peg
Parsing Expression Grammar (PEG) parser generator for Rust
Stars: ✭ 836 (+3534.78%)
Mutual labels:  parsing
Jackson Module Kotlin
Module that adds support for serialization/deserialization of Kotlin (http://kotlinlang.org) classes and data classes.
Stars: ✭ 830 (+3508.7%)
Mutual labels:  json
Html Table Cli
Create interactive tables from JSON on the command-line
Stars: ✭ 23 (+0%)
Mutual labels:  json

forma
[swe] verb. /fạ̊r:ma/
to adjust; adapt

Build Status

forma

Applies typespecs to JSON-like data.

This module can parse JSON-like data (such as maps with key strings) into a more structured form by trying to map it to conform to a module's typespec.

This can generally be useful when interfacing with external data sources that provide you data as JSON or MessagePack, but that you wish to transform into either proper structs or richer data types without a native JSON representation (such as dates or sets) in your application.

It is heavily inspired by Go's way of dealing with JSON data.

defmodule User do
  defstruct [:id, :name, :age, :gender]

  @type t :: %__MODULE__{
    id: String.t,
    name: String.t,
    age: non_neg_integer(),
    gender: :male | :female | :other | :prefer_not_to_say
  }
end

Forma.parse(%{"id" => "1", "name" => "Fredrik", "age" => 30, "gender" => "male"}, User)
# => {:ok, %User{id: "1", name: "Fredrik", age: 30, gender: :male}}

Forma tries to figure out how to translate its input to a typespec. However, not all types have natural representations in JSON, for example dates, or don't want to expose their internals (opaque types).

If you're in control of the module defining the type, you can implement the __forma__/2 function to handle parsing input to your desired type

defmodule App.Date do
  @opaque t :: Date

  # first argument is the type to be parsed in this module
  def __forma__(:t, input) do
    case Date.from_iso8601(input) do
      {:ok, date} -> date
      {:error, reason} -> raise reason
    end
  end
end

If you're not in control of the module, you can pass a parser along as an optional argument,

defmodule LogRow do
  defstruct [:log, :timestamp]

  type t :: %__MODULE__{
    log: String.t,
    timestamp: NaiveDateTime.t
  }
end

date = fn input ->
  case NaiveDateTime.from_iso8601(input) do
    {:ok, datetime} -> datetime
    {:error, err} -> raise err
  end
end
parsers = %{{NaiveDateTime, :t} => date}
Forma.parse(%{"log" => "An error occurred", "timestamp" => "2015-01-23 23:50:07"}, LogRow, parsers)

The number of arguments to the parser functions depends on if the type is parameterized or not (MapSet.t vs MapSet.t(integer)).

Installation

If available in Hex, the package can be installed by adding forma to your list of dependencies in mix.exs:

def deps do
  [
    {:forma, "~> 0.7.1"}
  ]
end

Documentation can be generated with ExDoc and published on HexDocs. Once published, the docs can be found at https://hexdocs.pm/forma.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].