NimYAML

Introduction

NimYAML is a pure YAML implementation for Nim. It is able to read from and write to YAML character streams, and to serialize from and construct to native Nim types. It exclusively supports YAML 1.2.

Source code can be found on GitHub. You can install it with Nimble:

nimble install yaml

Quickstart

Dumping reference types and cyclic structures

code.nim out.yaml import yaml . serialization , streams type Node = ref NodeObj NodeObj = object name : string left , right : Node var node1 , node2 , node3 : Node new ( node1 ) ; new ( node2 ) ; new ( node3 ) node1 . name = "Node 1" node2 . name = "Node 2" node3 . name = "Node 3" node1 . left = node2 node1 . right = node3 node2 . right = node3 node3 . left = node1 var s = newFileStream ( "out.yaml" , fmWrite ) dump ( node1 , s ) s . close ( ) %YAML 1.2 %TAG !n! tag:nimyaml.org,2016: --- &a name : Node 1 left : name : Node 2 left : ~ right : &b name : Node 3 left : *a right : ~ right : *b

Loading reference types and cyclic structures

code.nim in.yaml import yaml . serialization , streams type Node = ref NodeObj NodeObj = object name : string left , right : Node var node1 : Node var s = newFileStream ( "in.yaml" ) load ( s , node1 ) s . close ( ) %YAML 1.2 %TAG !n! tag:nimyaml.org,2016: --- &a name : Node 1 left : name : Node 2 left : ~ right : &b name : Node 3 left : *a right : ~ right : *b

Defining a custom tag uri for a type

code.nim out.yaml import yaml , streams type Mob = object level , experience : int32 drops : seq [ string ] setTagUri ( Mob , "!Mob" ) setTagUri ( seq [ string ] , "!Drops" ) var mob = Mob ( level : 42 , experience : 1800 , drops : @ [ "Sword of Mob Slaying" ] ) var s = newFileStream ( "out.yaml" , fmWrite ) dump ( mob , s , tagStyle = tsAll ) s . close ( ) %YAML 1.2 %TAG !n! tag:nimyaml.org,2016: --- level : 42 experience : 1800 drops : [ Sword of Mob Slaying ]

Customizing output style

code.nim out.yaml import yaml . serialization , yaml . presenter , streams type Person = object name : string age : int32 var personList = newSeq [ Person ] ( ) personList . add ( Person ( name : "Karl Koch" , age : 23 ) ) personList . add ( Person ( name : "Peter Pan" , age : 12 ) ) var s = newFileStream ( "out.yaml" , fmWrite ) dump ( personList , s , options = defineOptions ( style = psCanonical , indentationStep = 3 , newlines = nlLF , outputVersion = ov1_1 ) ) s . close ( ) %YAML 1.1 %TAG !n! tag:nimyaml.org,2016: --- [ { ? " name" : " Karl Koch" , ? " age" : " 23" } , { ? " name" : " Peter Pan" , ? " age" : " 12" } ]

Loading Nim objects from JSON

code.nim in.yaml import yaml . serialization , streams type Person = object name : string age : int32 var personList : seq [ Person ] var s = newFileStream ( "in.yaml" ) load ( s , personList ) s . close ( ) [ { " name" : " Karl Koch" , " age" : 23 } , { " name" : " Peter Pan" , " age" : 12 } ]

Dumping Nim objects as YAML

code.nim out.yaml import yaml . serialization , streams type Person = object name : string age : int32 var personList = newSeq [ Person ] ( ) personList . add ( Person ( name : "Karl Koch" , age : 23 ) ) personList . add ( Person ( name : "Peter Pan" , age : 12 ) ) var s = newFileStream ( "out.yaml" , fmWrite ) dump ( personList , s ) s . close ( ) %YAML 1.2 %TAG !n! tag:nimyaml.org,2016: --- - name : Karl Koch age : 23 - name : Peter Pan age : 12

Processing a Sequence of Heterogeneous Items

… With variant objects

code.nim in.yaml import yaml , streams type Person = object name : string ContainerKind = enum ckString , ckInt , ckBool , ckPerson , ckNone Container { . implicit . } = object case kind : ContainerKind of ckString : strVal : string of ckInt : intVal : int of ckBool : boolVal : bool of ckPerson : personVal : Person of ckNone : discard setTagUri ( Person , nimTag ( "demo:Person" ) ) var list : seq [ Container ] var s = newFileStream ( "in.yaml" ) load ( s , list ) s . close ( ) assert ( list [ 0 ] . kind == ckString ) assert ( list [ 0 ] . strVal == "this is a string" ) %YAML 1.2 %TAG !n! tag:nimyaml.org,2016: --- - this is a string - 42 - false - 23 - { name : Trillian } -

… With the Sequential API

code.nim in.yaml import yaml , streams type Person = object name : string setTagUri ( Person , nimTag ( "demo:Person" ) , yTagPerson ) var s = newFileStream ( "in.yaml" , fmRead ) context = newConstructionContext ( ) parser = newYamlParser ( serializationTagLibrary ) events = parser . parse ( s ) assert events . next ( ) . kind == yamlStartDoc assert events . next ( ) . kind == yamlStartSeq var nextEvent = events . peek ( ) while nextEvent . kind != yamlEndSeq : var curTag = nextEvent . tag ( ) if curTag == yTagQuestionMark : assert nextEvent . kind == yamlScalar case guessType ( nextEvent . scalarContent ) of yTypeInteger : curTag = yTagInteger of yTypeBoolTrue , yTypeBoolFalse : curTag = yTagBoolean of yTypeUnknown : curTag = yTagString else : assert false , "Type not supported!" elif curTag == yTagExclamationMark : curTag = yTagString case curTag of yTagString : var s : string events . constructChild ( context , s ) echo "got string: " , s of yTagInteger : var i : int32 events . constructChild ( context , i ) echo "got integer: " , i of yTagBoolean : var b : bool events . constructChild ( context , b ) echo "got boolean: " , b of yTagPerson : var p : Person events . constructChild ( context , p ) echo "got Person with name: " , p . name else : assert false , "unsupported tag: " & $ curTag nextEvent = events . peek ( ) assert events . next ( ) . kind == yamlEndSeq assert events . next ( ) . kind == yamlEndDoc assert events . finished ( ) s . close ( ) %YAML 1.2 %TAG !n! tag:nimyaml.org,2016: --- - this is a string - 42 - false - 23 - { name : Trillian }

Loading Nim objects from YAML

code.nim in.yaml import yaml . serialization , streams type Person = object name : string age : int32 var personList : seq [ Person ] var s = newFileStream ( "in.yaml" ) load ( s , personList ) s . close ( ) %YAML 1.2 --- - { name : Karl Koch , age : 23 } - { name : Peter Pan , age : 12 }

Dumping Nim objects as JSON