json marshalling of a complex structure in Golang [duplicate] - json

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!

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]]
}
}

Golang unmarshall nested dynamic JSON object in struct [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 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...

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.

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

[Go]: Parsing JSON [duplicate]

This question already has answers here:
Lowercase JSON key names with JSON Marshal in Go
(4 answers)
Closed 5 years ago.
What I am trying to do
I am parsing a JSON HTTP response based on this answer to a similar question. My code is able to parse the JSON without any error but is unable to read the values and store them in the provided variable.
This has been puzzling me for the last 2 hours and it might be due to a trivial reason that I am overlooking here.
CODE
type ImporterResponse struct {
results []packagemeta `json:"results"`
}
type packagemeta struct {
path string `json:"path"`
synopsis string `json:"synopsis,omitempty"`
count int `json:"import_count,omitempty`
}
func main() {
res := []byte(`{"results":[{"path":"4d63.com/randstr/lib/randstr","import_count":0,"synopsis":"Package randstr generates random strings (e.g."},{"path":"bitbucket.org/pcas/tool/mathutil","import_count":0}]}`)
fmt.Println("Decoding the JSON")
r := bytes.NewReader(res)
decoder := json.NewDecoder(r)
packageimporters := &ImporterResponse{}
err := decoder.Decode(packageimporters)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Packageimporters: %+v", packageimporters)
fmt.Println(len(packageimporters.results))
}
Link to Playground: https://play.golang.org/p/NzLl7Ujo2IJ
What I want:
How to fix this?
Why is no error message raised if JSON is not parsed properly?
P.S: I understand that this question has been asked before and there are possible solutions available but none of them work for me. Hence, I have made this post.
You need to make your struct fields exported, otherwise the json package cannot access them.
Please read JSON and go for more details, specifically this paragraph:
The json package only accesses the exported fields of struct types
(those that begin with an uppercase letter). Therefore only the the
exported fields of a struct will be present in the JSON output.
And this one for more details:
How does Unmarshal identify the fields in which to store the decoded
data? For a given JSON key "Foo", Unmarshal will look through the
destination struct's fields to find (in order of preference):
An exported field with a tag of "Foo" (see the Go spec for more on
struct tags),
An exported field named "Foo", or
An exported field
named "FOO" or "FoO" or some other case-insensitive match of "Foo".
So your struct should really be:
type Packagemeta struct {
Path string `json:"path"`
Synopsis string `json:"synopsis,omitempty"`
Count int `json:"import_count,omitempty`
}