`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()