I isolated strange case where error message why it can't convert to JSON is very misleading.
Please try code online to see it, click the "Run" button https://repl.it/@alexeypetrushin/jsonerror#main.nim
Nim complained that State can't be converted to JSON when in reality the problem was that proc save*(c: Container): void wad declared without specifying generic parameter for Container as proc save*(c: Container[string]): void.
Not sure if it's a bug or maybe I'm missing something.
And if slightly modified, it produces another strange bug, if instead of 2 separate files everything united in 1 file it works.
@Araq thanks, seems to be a tricky bug indeed :).
Do you know if there's a workaround? Can you please take a look at this example, would it be possible to implement it? About the example - in one file the generic crawler is defined, and in another file the specific process proc to handle specific crawling task.
Executable version, hit "Run" https://repl.it/@alexeypetrushin/how-to-create-crawler#main.nim
crawler.nim file
import json
type
Job* = object of RootObj
id*: string
Processed* = object
result: string
Crawler*[J] = object
jobs*: seq[J]
proc run*[J: Job](crawler: Crawler[J]): void =
var processed: seq[Processed] = @[]
for job in crawler.jobs:
let result: string = job.process()
processed.add Processed(result: result)
echo %(processed)
main.nim file
import crawler
type GetPriceJob = object of Job
symbol: string
proc process*(job: GetPriceJob): string = "Price for " & job.symbol & " = 500 USD"
Crawler[GetPriceJob](
jobs: @[
GetPriceJob(symbol: "MSFT")
]
).run()
#crawler.nim
include json
#i guess %[T:object] and the `$`(JsonNode) procs aren't instantiated if they're not used?
type
Job* = object of RootObj
id*: string
Processed* = object
result: string
Crawler*[T] = object
jobs*: seq[T]
method process*(j: Job): string{.base.} = "default" #dynamic dispatch time.
proc run*(crawler: Crawler): void = #no need for generics here idk
var processed: seq[Processed] = @[]
for job in crawler.jobs:
let res: string = job.process()
processed.add Processed(result: res)
echo %processed
#main.nim
import crawler
type GetPriceJob = object of Job
symbol: string
method process*(job: GetPriceJob): string = "Price for " & job.symbol & " = 500 USD"#method again
Crawler[GetPriceJob](jobs: @[
GetPriceJob(symbol: "MSFT")
]
).run()
but you know Crawler can't have more than one type of Job in it's queue, right? for a heterogeneous Crawler you'll need to:
type
Job* = ref object of RootObj #ref so they all fit in the Container
id*: string
Processed* = object
result: string
Crawler* = object
jobs*: seq[Job]
#oh, and also this was one reason it was choking, "process" needs to be defined here where you use it
method process*(j: Job): string{.base.} = j.id #dynamic dispatch time.
proc run*(crawler: Crawler): void = #no need for generics here idk
var processed: seq[Processed] = @[]
for job in crawler.jobs:
let res: string = job.process()
processed.add Processed(result: res)
echo %processed
#main.nim
import crawler
type GetPriceJob = ref object of Job
symbol: string
method process*(job: GetPriceJob): string = "Price for " & job.symbol & " = 500 USD"#method again
Crawler(jobs: @[
GetPriceJob(symbol: "MSFT"),
Job(id:"blargle")
]
).run()
Thank you, I forgot about the OOP way :). One question - what is this line for?
import json
export json