Golang unmarshall nested dynamic JSON object in struct [duplicate] - json

This question already has answers here:
Is it possible to partially decode and update JSON? (go)
(2 answers)
How to parse a complicated JSON with Go unmarshal?
(3 answers)
golang | unmarshalling arbitrary data
(2 answers)
How to parse JSON in golang without unmarshaling twice
(3 answers)
Decoding generic JSON objects to one of many formats
(1 answer)
Closed 9 months ago.
I have a JSON in the following format:
{
"fieldA": {
"dynamicField": "string value",
"moreDynamicField": ["or", "array", "of", "strings"],
"allFieldsAreDynamic": "values in str or arr[str] only"
},
"fieldB": {
"dynamicField": "sameAsThoseInFieldA",
}
}
The outer fields are fixed, but each outer field's value is a dynamic object. Therefore, I attempted to unmarshall this data into the following Go struct:
type JsonData struct {
fieldA map[string]interface{}
fieldB map[string]interface{}
}
func main() {
var data JsonData
json.Unmarshal([]byte(`{"fieldA": {"x":"x", "y":["x","y"]}, "fieldB": {"a":"b", "c":"d"}}`), &data)
fmt.Println(data)
}
However, the above code produces empty Go array with no error: {map[] map[]}. I also tried fieldA map[string]map[string]any but the result is the same.
I didn't spot useful information on the json package documentation about this nested unmarshalling. Plus, will there be a performance drop using pure map[string]interface{} for the entire JSON data? Some benchmarking blogs and reddit tales gives contradictory conclusions...

Related

How to parse same filed with different formats in Go json.Unmarshal? [duplicate]

This question already has answers here:
Is it possible to partially decode and update JSON? (go)
(2 answers)
How to parse a complicated JSON with Go unmarshal?
(3 answers)
golang | unmarshalling arbitrary data
(2 answers)
How to parse JSON in golang without unmarshaling twice
(3 answers)
Decoding generic JSON objects to one of many formats
(1 answer)
Closed 9 months ago.
How to parse old json and new json simultaneously with the same struct and filed?
I am new to Go, is there any easier way to solve it? Thanks so much for any advice.
I would like to parse Json from MQTT, and I can parsed below old json successfully with below Go code, now we have new json with different formats only with test filed, and I will got the error of json: cannot unmarshal array into Go struct field Skill.SKILL.Test of type float64 when parse new json.
Old json
{
"ID" : "1",
"SKILL" : {
"name" : "test_name",
// index is the `ID` of value, the length of the list is settled
"test" : [23.1234, 15.2345, 25.2341, 27.1234, 14.2345, 16.2341,17.2341]
}
}
Go code
package main
import (
"encoding/json"
)
type MyProject struct {
Id string `json:"Id"`
Skill Skill `json:"SKILL"`
}
type Skill struct {
Name string `json:"Name"`
Test []float64 `json:"Test"`
}
func main(client mqtt.Client, msg mqtt.Message) {
myproject := MyProject{}
err := json.Unmarshal(msg.Payload(), &myproject)
test := myproject.Skill.Test
}
New json
Now we have new json as below from MQTT server:
{
"ID" : "1",
"SKILL" : {
"name" : "test_name",
// `1`,`2`,`3` is the `ID` of value,the length of the list is settled
"test" : [[1, 23.1234], [2, 13.2345], [3, 26.2341]]
}
}

Representing a list of things of different type in JSON and Golang [duplicate]

This question already has answers here:
Is it possible to partially decode and update JSON? (go)
(2 answers)
How to parse a complicated JSON with Go unmarshal?
(3 answers)
golang | unmarshalling arbitrary data
(2 answers)
How to parse JSON in golang without unmarshaling twice
(3 answers)
Decoding generic JSON objects to one of many formats
(1 answer)
Closed 9 months ago.
I'm trying to represent some data in JSON where there is a list of things where each thing has some common features (ex name) and another field who's value can either be a string or an integer. For example:
{
"items": [
{
"name": "thing1",
"type": "string",
"value": "foo"
},
{
"name": "thing2",
"type": "int",
"value": 42
}
]
}
That JSON looks reasonable to me, but trying to create a data structure to deserialize (unmarshal) it into in Golang is proving difficult. I think I could do it in Java with class polymorphism, but in Go I feel trapped. I've tried many things but haven't got it. Ultimately, it comes down to lack of struct type polymorphism.
In Go, I can have a slice (list) of interfaces, but I need actual structs of different types as far as I can tell.
Any suggestions on how to represent this in Golang, and be able to unmarshal into?
Or alternatively, should I structure the JSON itself differently?
Thanks!
You can create a structure like this
type items struct {
name string
type_1 string
value interface{}
}
Interface can hold any data type, also as type is reserved keyword i have used type_1
You can do it in Go 1.18 like this:
type Data struct {
Items []struct {
Name string `json:"name"`
Type string `json:"type"`
Value any `json:"value"`
} `json:"items"`
}
func main() {
data := Data{}
// it's your json bytes
bytesData := []byte()
if err := json.Unmarshal(byteData, &data); err != nil {
log.Fatal(err)
}
}
// use data here
P.S. if you are using older versions use interface{} instead of any.
This data structure properly represents your JSON:
type Data struct {
Items []struct {
Name string `json:"name"`
Type string `json:"type"`
Value interface{} `json:"value"`
} `json:"items"`
}
Then, you can use json.Unmarshal.
If you use Go 1.18, you can use any alias of interface{}.
In addition, in Go you don't even need a type field. You can use Type assertions to determine the value type.

json marshalling of a complex structure in Golang [duplicate]

This question already has answers here:
Serialize a mixed type JSON array in Go
(3 answers)
Golang decoding JSON into slice with one string and one float64
(1 answer)
Fixed-size array that contains multiple specific types?
(1 answer)
Closed 3 years ago.
I just started developing in Golang, and am up against this problem:
I have json data to be accepted by a Golang server. A sample of one of the fields of this json data is below:
"DATA":[["(610, 658)",1573824148],["(594, 675)",1573824148],["(578,710)",1573824148],["(571, 728)",1573824148],["(552, 769)",1573824148],["(549, 788)",1573824148],["(549, 796)",1573824148]]
Note that it is an array of lists, each list being a string and an integer.
I have the following data structures declared:
type POINT struct {
p string
t int
}
type POINTS struct {
A int
B int
C string
DATA []FIDGET
}
The relevant field is POINTS.DATA which is an array of POINTs. A POINT is a string and an int. To convert from json to Go variables, I use the encoding/json package.
My problem is, when I call
err = json.Unmarshal(body, &m)
I get this error:
json: cannot unmarshal array into Go struct field POINTS.DATA of type main.POINT
Can anyone help me? Thank you in advance!

unmarshall json using dynamic key [duplicate]

This question already has answers here:
Golang parse a json with DYNAMIC key [duplicate]
(1 answer)
How to parse/deserialize dynamic JSON
(4 answers)
Marshal dynamic JSON field tags in Go
(1 answer)
How to Unmarshal jSON with dynamic key which can't be captured as a `json` in struct: GOlang [duplicate]
(1 answer)
Closed 4 years ago.
I'm receiving a json object that has a known-static structure inside a key that varies between 10 different values.
Consider lastname can be any in a list of 10 lastnames:
var lastnames = [...]string { "Smith", "Johnson", "Williams", "Brown", "Jones", "Miller", "Davis", "Garcia", "Rodriguez", "Wilson" }
Now, this is how the json looks:
{
(lastname here):
{
"position": value,
"user_email": value
}
}
I tried to unmarshall it using the following structs, but I only get null values:
type Inside struct {
Rol string `json:"position"`
Email string `json:"user_email"`
}
type Outside struct {
Key Inside
}
...
var outside Outside
json.Unmarshal([]byte(body), &outside)
Is it possible to unmarshall this directly without creating 10 different structs? Is there possible workaround?

How to deserialize list with mixed types? [duplicate]

This question already has answers here:
Unmarshal 2 different structs in a slice
(3 answers)
Closed 4 years ago.
How would I deserialize this JSON in Go?
{
"using": [ "jmap-core", "jmap-mail" ],
"methodCalls": [
["method1", {"arg1": "arg1data", "arg2": "arg2data"}, "#1"],
["method2", {"arg1": "arg1data"}, "#2"],
["method3", {}, "#3"]
]
}
I haven't figured out how to properly get the json module to parse the methodCalls into a type. My first idea was
type MethodCall struct {
Name string
Params map[string]string
ClientId string
}
and then to use it as a list type:
type Request struct {
Using []string
MethodCalls []MethodCall
}
But this does not work. :using" is correctly parsed, but the "methocCalls" are not. Is there a way to get Go to parse this JSON into my types?
It looks like the methodCalls that you are trying to deserialize it is an array of strings instead of a struct for MethodCall.
So, Take a look at this link that I am deserializing as an array.
If you want to use the MethodCall struct you have to change the json a little bit. Take a look at this link