Giter Site home page Giter Site logo

presqueyaml's Introduction

โœจ MagnusOpera.PresqueYaml

PresqueYaml is a Yaml parser and deserializer.

In French, "presque" means "almost". If you understand it right, PresqueYaml is not a fully compliant yaml parser. Don't worry, it does support most features!

If you want a strict 1.2 yaml parser, do not use this project: missing features will probably never be implemented as I consider them either misleading or niche cases.

PresqueYaml is written in F# and offers:

  • Yaml deserialization to a representation model.
  • Map representation model to an object model:
    • F# support: list<>, map<string,>, option<>, unit and record.
    • C# support: List<>, Dictionary<string,>, Nullable<> and class (via unique constructor).
    • YamlNode/YamlNodeValue<>: useful for structure validation (object model driven schema ๐Ÿ˜…).
  • Support net7.0+ and NRT (Nullable Reference Types).
  • Extensible, small and easily maintainable.

๐Ÿง Key differences with Yaml (all versions)

It's probably not exhaustive ! Again, `PresqueYaml` does not pretend to support full Yaml specification. You have been warned if you heavily rely on this.

Blocks

PresqueYaml only supports explicit and proper nested blocks as follow.

+--[block1]-------------x
|
|  +--[block2]----------x
|  |
|  x
|
|  +--[block3]----------x
|  |
|  |
|  x
|
x

A block can either be a mapping, sequence or scalar. In any cases, explicitness is mandatory - this is a key difference with Yaml specification (where implicit flow literal with dedent is allowed for eg).

Scalars

  • single and double quoted strings are handled exactly the same.
  • scalar are either compact (and multilines with same indentation), folded or literal. Implicit flow scalar with dedent is not supported for eg.
  • only escapes \n, \r, \tand \s are supported.
  • representation model is always using stringtype - it does not attempt to identify types: that's subsequent analyzer or deserializer responsibility.

Sequences

  • compact sequences do not support quoted strings - only raw content.
  • Sequence must be strictly indented respective to parent node.

Mappings

  • quoted string keys are not allowed - they are of string type (without any spaces) and ends with : character.
  • mapping can have duplicated keys (last key wins).
  • compact mappings (single line) are not supported.
  • mappings can be nested on same line (think nested block) - it's not encouraged since it's a clear departure from Yaml.

Comments

  • a line is either empty, comment or content. Mixed content is not supported.

Documents

  • no support for multiple document in one yaml file.
  • no schema support.
  • no tag support.

๐Ÿš€ Supported feature example

Anyway, most Yaml documents do not use advanced features. Here is a document showing PresqueYaml capabilities:

# scalars
scalar: this is a scalar
implicitFoldedScalarMultiline: this
                               is
                               a
                               scalar
noneScalar:
scalarSingleQuoted: '  this is a single quoted \\nscalar  '
scalarDoubleQuoted: \"  this is a double quoted \\nscalar  \"
scalarFolded: |
  this
    is
      a
        scalar
scalarLiteral: >
  this
    is
      a
        scalar

# sequences
sequence:
  - item1
  - item2
  -
  - item3
nestedSequence:
  - - item11
    - item12
  - - item21
    - item22
flowSequence: [   item1, item2, item3   ]
mappingInSequence:
  - item1: value1
    item2: value2
  - item3: value3
    item4:

# mappings
mapping:
  item1: value1
  item2: value2
  item3:
# note: this is something not valid in Yaml spec - usage is discouraged
#       but it's valid per block definition in PresqueYaml
nestedMapping: item1: value1
               item2: value2

F# representation model:

YamlNode.Mapping (Map [ // scalars
                        "scalar", YamlNode.Scalar "this is a scalar"
                        "implicitFoldedScalarMultiline", YamlNode.Scalar "this is a scalar"
                        "noneScalar", YamlNode.None
                        "scalarSingleQuoted", YamlNode.Scalar "  this is a single quoted \nscalar  "
                        "scalarDoubleQuoted", YamlNode.Scalar "  this is a double quoted \nscalar  "
                        "scalarFolded", YamlNode.Scalar "this\n  is\n    a\n      scalar"
                        "scalarLiteral", YamlNode.Scalar "this   is     a       scalar"

                        // sequences
                        "sequence", YamlNode.Sequence [ YamlNode.Scalar "item1"
                                                        YamlNode.Scalar "item2"
                                                        YamlNode.None
                                                        YamlNode.Scalar "item3" ]
                        "nestedSequence", YamlNode.Sequence [ YamlNode.Sequence [ YamlNode.Scalar "item11"
                                                                                  YamlNode.Scalar "item12" ]
                                                              YamlNode.Sequence [ YamlNode.Scalar "item21"
                                                                                  YamlNode.Scalar "item22" ] ]
                        "flowSequence", YamlNode.Sequence [ YamlNode.Scalar "item1"
                                                            YamlNode.Scalar "item2"
                                                            YamlNode.Scalar "item3" ]
                        "mappingInSequence", YamlNode.Sequence [ YamlNode.Mapping (Map [ "item1", YamlNode.Scalar "value1"
                                                                                         "item2", YamlNode.Scalar "value2" ])
                                                                 YamlNode.Mapping (Map [ "item3", YamlNode.Scalar "value3"
                                                                                         "item4", YamlNode.None ]) ]

                        // mappings
                        "mapping", YamlNode.Mapping (Map [ "item1", YamlNode.Scalar "value1"
                                                           "item2", YamlNode.Scalar "value2"
                                                           "item3", YamlNode.None ])
                        "nestedMapping", YamlNode.Mapping (Map [ "item1", YamlNode.Scalar "value1"
                                                                 "item2", YamlNode.Scalar "value2" ]) ])

๐Ÿ“š Api

PresqueYaml can be used both in F# and C#. F# is preferred of course to explore the representation model. Namespace of API is MagnusOpera.PresqueYaml.

Availability

Nuget

Build status

Requirements

PresqueYaml targets net7.0 and more.

Parser

In order to convert a yaml document to a representation model, use:

let yaml = "value: toto"
let node = YamlParser.Read yaml
// node is of type YamlNode

Representation model is:

[<RequireQualifiedAccess>]
type YamlNode =
    | None
    | Scalar of string
    | Sequence of YamlNode list
    | Mapping of Map<string, YamlNode>

Deserialization

To convert a representation model to a .net object model, use:

let node = ... // representation model
let map = YamlSerializer.Deserialize<Map<string, string>>(node)
// map is of type Map<string, string>

Special types

By default, PresqueYaml manages:

  • Byte, Char, Int16, UInt16, Int32, UInt32, Int64, UInt64, String
  • C# Array, List<_>, Dictionary<string, >, Nullable<>, class (must define primary constructor only)
  • F# list<>, Set<>, Map<string, _>, option, unit, record
  • YamlNode and YamlNodeValue<_>

YamlNodeValue<_> allows to discover if a value is provided:

  • has not been provided (Undefined)
  • has not been set (None)
  • has been set (Value)

Specific behaviors

By default, following types have a default value:

Type Default value
reference types null if NRT enabled and type is nullable
Collections (both F# and C#) empty
YamlNodeValue YamlNodeValue.Undefined

This behavior can be changed by providing a YamlDeserializationOptions on Deserialize.

โš ๏ธ NOTE: NRT support is provided at runtime (it's reflection based). Depending on activation context, you may observe different behaviors:

  • C# + Nullable enable: NRT are enforced and reference types can be nullable
  • C# + Nullable disabled: NRT are disabled and reference types can't be nullable
  • F#: NRT are not supported and reference types can't be nullable

Customization

YamlDeserializer must be given a configuration. This configuration instructs:

  • which mappers to use.
  • how to deserialize YamlNode.None regarding collections.

There is a default configuration provided (YamlDefaults.options):

  • Include all F# and C# types
  • YamlNode.None forces empty collections.
Property Default Description
Converters F# and C# mappers List of converters to use for deserialization
NoneIsEmpty true Convert YamlNode.None to empty collection

presqueyaml's People

Contributors

pchalamet avatar

Stargazers

Masashi Fujita avatar  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.