Alex Craft
Alex Craft

Reputation: 15366

How to convert sequence of objects to JSON in Nim?

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?

Upvotes: 3

Views: 582

Answers (1)

xbello
xbello

Reputation: 7443

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

Upvotes: 1

Related Questions