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_refT: 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?
Nim loves object variants
import marshal
type
DocKind = enum
TextDoc,TodoDoc
DocItem = object
case kind:DocKind
of TextDoc:
text:string
of TodoDoc:
todo:string
tags:seq[string]
var docs: seq[DocItem]
docs.add DocItem(kind:TextDoc, text: "some doc", tags: @["help"])
docs.add DocItem(kind:TodoDoc,todo: "some todo")
echo $$docs
Thanks, I like object variants, but it's not always possible to use it, I would like to find a general solution.
I'm trying to use Nim for data analytics, and there are lots of data passing in and out and integration with Node.JS and Python scripts via JSON.
Also, it seems like it's a bit to early and unsafe to use it, as compiler currently not validating it during the compile time, code below would produce runtime error:
type
DocKind = enum
TextDoc, TodoDoc
DocItem = object
case kind:DocKind
of TextDoc:
text:string
of TodoDoc:
todo:string
let doc = DocItem(kind:TextDoc, text: "some doc")
echo doc.text
echo doc.todo
I'm trying to improve stability and correctness of the project made with Node and Python. By rewriting some of its parts in Type Safe language. Using not type safe constructs like object variants kinda defeats the whole purpose of the work.
I'm currently have to choose between Kotlin and Nim.
I know Java and Kotlin, but while they should do the job and made project more safe, I'm not a huge fan of Java and try to find something better.
Currently trying to estimate if I can use Nim in that project. And I'm absolutelly can't do that if Nim is unable to perform such a simple task as convert list of objects to JSON.
DocItem(kind:TextDoc, text: "some doc").text
then it should compile fine.I believe the compiler error is because you are trying to access the todo attribute which does not exist for your object.
Exactly, I made that error intentionally to show that it won't be caught by compiler and leak into runtime. The problem is not that there's an error, but that it's runtime error.
I may be wrong, but I think that @alexeypetrushin complains that the compiler did not catch the error at compile time, but only at runtime.
Using OOP, the problem would not occur as the field todo would be only visible in the subclass. Here, detecting the error is possible but will require some improvement in the compiler.
The marshal module is not meant to be a json serializer. This is for storing nim objects to disk and load it again (like python's pickle). It just happens to be json at the moment
For serializing json have a look at the json module.
I must say the json module is also a little bit limited, so I would also have a look at another serializing library: https://github.com/status-im/nim-serialization
Thanks, sadly it also won't output the fields from the child classes, the code
import serialization, json_serialization
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 Json.encode(docs, pretty = false)
Outputs only the fields from the parent object
[{"tags":["help"]},{"tags":[]}]
I don't think it's true that objects have better support than variants, variants are pretty integral to Nim.
I just read your blog post : I appreciate your passion.
import sequtils,json
let j = docs.mapIt:
if it of TodoDoc:
%TodoDoc(it)
else:
%TextDoc(it)
echo %j
Just as you'd have to do in Java when unpacking from a container and testing with instanceofYeah, you really shouldn't use marshal, especially when json gives you exactly the same output with very few changes:
import json
type
DocKind = enum
TextDoc, TodoDoc
DocItem = object
case kind:DocKind
of TextDoc:
text: string
of TodoDoc:
todo: string
tags: seq[string]
var docs: seq[DocItem]
docs.add DocItem(kind:TextDoc, text: "some doc", tags: @["help"])
docs.add DocItem(kind:TodoDoc,todo: "some todo")
echo %docs
And yes, @alexeypetrushin, I would suggest avoiding inheritance as much as you can. Object variants are the way to go.