Find the right struct for json data

296 views
Skip to first unread message

Julien Vehent

unread,
Aug 11, 2014, 9:44:38 AM8/11/14
to golan...@googlegroups.com
Hi everyone,

I am looking for a way to parse JSON data into the right struct.

My project uses modules that receive parameters in various formats. Each
module exports a struct that represent its parameters format. I am looking
for a way to find out which module a given JSON data belongs to.

So far, I have been hardcoding the list of modules and used a switch
to unmarshal the json into the proper module's struct. But every time a
module is added, I need to update the switches in the main program.

In other words, I am trying to make this code work: http://play.golang.org/p/kRaDJ2eEmM

Is there a way to make it generic enough such that I don't need to hardcode
the list of modules in the main program?

Thanks for the help!

- Julien

Péter Szilágyi

unread,
Aug 11, 2014, 9:49:29 AM8/11/14
to Julien Vehent, golang-nuts
Hi,

  One way would be to do it with reflection. You maintain a list of possible structs, and for each JSON message you iterate over its fields and try to match them up with the struct fields. I haven't used reflection in Go so I cannot provide a concrete solution, but it should be fairly straightforward. Of course speed-wise it will take a hit, but if you can afford it, then it is a simple and elegant solution.

Cheers,
  Peter



- Julien

--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Alex Zylman

unread,
Aug 11, 2014, 8:19:23 PM8/11/14
to golan...@googlegroups.com, jul...@linuxwall.info
Do you have control over the format your data comes in? To me it seems like a better solution is to take in data in a consistent format, rather than trying to account for an inconsistent format and determine at runtime what type of struct it needs to be unmarshaled into.

rogerjd

unread,
Aug 11, 2014, 9:14:57 PM8/11/14
to golan...@googlegroups.com, jul...@linuxwall.info
If the struct type is not known in advance, give json.Unmarshal a pointer to interface{}, and it will output a map[string]interface{}, whose keys are json field names and whose
values are the corresponding values stored as interface{}s

//note: untested and needs error checking

var object interface{}
json.Unmarshal("your json string", &object)
jsonObject = object.(map[string]interface{})  //unchecked type assertion

Thanks to
Mark Summerfield 
Programming in Go

Roger

Francisco Dalla Rosa Soares

unread,
Aug 12, 2014, 12:24:22 AM8/12/14
to Péter Szilágyi, Julien Vehent, golang-nuts


2014年8月11日月曜日、Péter Szilágyi<pet...@gmail.com>さんは書きました:

Siddon Tang

unread,
Aug 12, 2014, 1:51:12 AM8/12/14
to golan...@googlegroups.com, jul...@linuxwall.info
Maybe:

1, use json.RawMessage, then delay to decode it in proper module later 
2, every module register a name, you can dispatch the RawMessage to the specified module with name in your config 

在 2014年8月11日星期一UTC+8下午9时44分38秒,Julien Vehent写道:

Klaus Post

unread,
Aug 12, 2014, 5:06:58 AM8/12/14
to golan...@googlegroups.com, jul...@linuxwall.info
Hi!

I am not sure, but are you trying to achieve this?


(I used https://github.com/ChimeraCoder/gojson to generate the initial struct and then adjusted it)

Of course your parameters are in a map[string]interface{}, but I don't really see any better way to do it (and they are rather easy to iterate and type assert).

Regards, Klaus

Fatih Arslan

unread,
Aug 12, 2014, 5:10:24 AM8/12/14
to golang-nuts
You could also benefit from this package:

https://github.com/mitchellh/mapstructure

It allows you nicely decode map[string]interface{} into custom structs.

--
Fatih Arslan

Julien Vehent

unread,
Aug 15, 2014, 6:24:01 PM8/15/14
to Fatih Arslan, golang-nuts
Thanks for all the replied. mapstructure definitely looks interesting.
I'm also going to change my approach and use the `module` value to parse
the data using an interface from the right module.

- Julien

Matthew Holt

unread,
Aug 16, 2014, 12:20:02 AM8/16/14
to golan...@googlegroups.com, fa...@arslan.io, jul...@linuxwall.info
For future reference, if you know what the JSON looks like, there's also this quick-and-dirty tool to make a Go type def for you: http://mholt.github.io/json-to-go/ -- it can save you a few minutes of mundane typing.

Patrick Juchli

unread,
Aug 16, 2014, 4:42:49 AM8/16/14
to golan...@googlegroups.com, fa...@arslan.io
I found by benchmarking that using the naive approach with json.Marshal/Unmarshal is significantly faster and less memory intensive than using mapstructure. I was surprised by this but in the end it meant one dependency less for my case.
Reply all
Reply to author
Forward
0 new messages