`loadToJson` ignores tags because the JSON structures do not know anything 
about tags. You have several options:

**Using the serialization API with an implicit variant object**

First, you need to define the type for the tag `!remote`. You need to tell 
NimYAML how to load that type. Then, you define a variant object type that can 
hold either normal strings or `!remote` values. You then tell NimYAML to treat 
this variant object type implicitly for loading the chapters. Example code:
    
    
    import yaml.serialization, yaml.taglib
    
    type
      Remote = distinct string
      ChapterKind = enum
        ckLocal, ckRemote
      Chapter = object
        case kind: ChapterKind
        of ckLocal:
          lValue: string
        of ckRemote:
          rValue: Remote
      Root = object
        chapters: seq[Chapter]
    
    proc constructObject*(s: var YamlStream, c: ConstructionContext,
                          result: var Remote) =
      # construct a Remote like a string
      constructObject(s, c, string(result))
    
    setTagUri(Remote, "!remote")
    markAsImplicit(Chapter)
    
    var root: Root
    load("""
    chapters:
      - foo
      - bar
      - !remote http://example.com/somefile
    """, root)
    
    echo "Parsed chapters:"
    for c in root.chapters:
      case c.kind
      of ckLocal: echo "[Local] ", c.lValue
      of ckRemote: echo "[Remote] ", string(c.rValue)
    

Sadly, you cannot simply transform the chapter values into some `tuple[value: 
String, remote: bool]` because NimYAML's serialization API uses tags to denote 
types, not annotations.

**Using the DOM API**

Perhaps simpler for simple use cases:
    
    
    import yaml.dom
    
    var document = loadDOM("""
    chapters:
    - foo
    - bar
    - !remote http://example.com/somefile
    """)
    
    echo "Parsed chapters:"
    for c in document.root.pairs[0].value.children:
      echo if c.tag == "!remote": "[Remote] " else: "[Local] ", c.content
    

The DOM API needs some love; currently mappings are parsed into a 
`seq[tuple[key, value: YamlNode]]` which is not ideal for accessing specific 
subtrees. A Table would make more sense. Pull requests are welcome :).

**Using the sequential API**

This may be useful for use cases where you need to process the input 
sequentially since it doesn't load everything in an object and therefore is 
faster:
    
    
    import yaml.parser, yaml.taglib, yaml.stream
    
    var
      myTagLib = initCoreTagLibrary()
      yTagRemote = myTagLib.registerUri("!remote")
      p = newYamlParser(myTagLib)
      events = p.parse("""
    chapters:
      - foo
      - bar
      - !remote http://example.com/somefile
    """)
    
    doAssert events.next().kind == yamlStartDoc
    doAssert events.next().kind == yamlStartMap
    let key = events.next()
    doAssert key.kind == yamlScalar
    doAssert key.scalarContent == "chapters"
    doAssert events.next().kind == yamlStartSeq
    var cur = events.next()
    echo "Parsed chapters:"
    while cur.kind != yamlEndSeq:
      doAssert cur.kind == yamlScalar
      echo if cur.scalarTag == yTagRemote: "[Remote] " else: "[Local] ", 
cur.scalarContent
      cur = events.next()
    doAssert events.next().kind == yamlEndMap
    doAssert events.next().kind == yamlEndDoc
    doAssert events.finished()
    
    

Reply via email to