How to convert sequence of objects to JSON in Nim?

Viewed 373

I'm trying to convert list of objects to JSON, but it won't serialise it properly

import marshal

type
  DocItem = object of RootObj
    tags: seq[string]

  TextDoc = object of DocItem
    text: string

  TodoDoc = object of DocItem
    todo: string

var docs: seq[ref DocItem]

proc to_ref[T](o: T): ref T =
  result.new
  result[] = o

docs.add TextDoc(text: "some doc", tags: @["help"]).to_ref
docs.add TodoDoc(todo: "some todo").to_ref

echo $$docs

The output is:

[[4312834120, {"tags": ["help"]}], [4312834280, {"tags": []}]]

While I need it to be

[{"text": "some doc", "tags": ["help"]}, {"todo": "some todo", "tags": []}]

Also, is there a way to configure marshal to output pretty JSON?

1 Answers

Unfortunately the marshaling seems correct: it shows the pointer to the ref Object. Maybe you can resort to composition instead of inheritance:

import marshal


type
  Todo = object of RootObj
    todo: string

  Text = object of RootObj
    text: string

  DocItem = object of RootObj
    tags: seq[string]
    text: Text
    todo: Todo

var docs: seq[DocItem] = @[]

docs.add DocItem(tags: @["help"], todo: Todo(todo: "some todo"))
docs.add DocItem(tags: @["help"], text: Text(text: "some text"))

echo $$docs

Or maybe you can try object variants. I'm adding a new imaginary "Link" type to illustrate it better:

import marshal


type
  Content = enum
    tTodo
    tText
    tImage

  DocItem = object of RootObj
    tags: seq[string]
    case kind: Content
    of tTodo, tText:
      text: string
    of tLink:
      url: string

var docs: seq[DocItem] = @[]

docs.add DocItem(tags: @["help"], kind: tTodo, todoVal: "some todo")
docs.add DocItem(tags: @["help"], kind: tText, textVal: "some text")
docs.add DocItem(tags: @["help"], kind: tLink, url: "http://stackoverflow.com")

echo $$docs
Related