Dynamically Allocating Stucture - json

I have a struct:
type person struct{
FirstN [10]byte
Last Name [10]byte
Address [15]byte
zip [6]byte
}
Then I have Map
xyz = [01:aaaaaaaaaabbbbbbbbbbccccccccccccccc123456]
This map is exactly the same as my struct. Basically if I overlay my structure with the string in the map it is an exact match.
I am trying to get a JSON string for this data, using Marshal. But for that (as I understand it) I need to update the data in the map into the struct and then pass the structure pointer to Marshal
But I cannot find any way to get the data from the map with key '01' which is a string and initialize my structure with it. I do not want to add a code to update each field in the structure by parsing the string from the map. Is there a way to do it or hardcoding is the only option.
Also is there a way to create a JSON string from a map string directly?

That's not json data. However, the binary.Read function will decode arbitrary fixed sized values from a binary stream following the struct layout.
data := []byte("aaaaaaaaaaaaaaaaaaaaccccccccccccccc123456")
err := binary.Read(bytes.NewReader(data), binary.LittleEndian, &p)
https://play.golang.org/p/-I_XhUCvNN

Related

How do I parse JSON in Go where array elements have more than one type?

How can I parse a JSON response from https://api.twitchinsights.net/v1/bots/online to an array in Go and iterate over every entry?
I dont understand the struct because there are no keys only values...
Can anyone please help and explain how this works?
I've mapped it but then I get something like
map[_total:216 bots:[[anotherttvviewer 67063 1.632071051e+09] [defb 26097 1.632071051e+09] [commanderroot 17531 1.632071048e+09] [apparentlyher 16774 1.63207105e+09]...
But I cant iterate over the map.
Because the API you're working with returns data where it could be a string or a number (in the array of arrays property bots), you'll need to use []interface{} as the type for each element of that array because the empty interface (https://tour.golang.org/methods/14) works for any type at run time.
type response struct {
Bots [][]interface{} `json:"bots"`
Total int `json:"_total"`
}
Then, as you iterate through each item in the slice, you can check its type using reflection.
It would be ideal for the API to return data in a schema where every JSON array element has the same JSON type as every other element in its array. This will be easier to parse, especially using statically typed languages like Go.
For example, the API could return data like:
{
"bots": [
{
"stringProp": "value1",
"numberProps": [
1,
2
]
}
],
"_total": 1
}
Then, you could write a struct representing the API response without using the empty interface:
type bot struct {
StringProp string `json:"stringProp"`
NumberProps []float64 `json:"numberProps"`
}
type response struct {
Bots []bot `json:"bots"`
Total int `json:"_total"`
}
But sometimes you're not in control of the API you're working with, so you need to be willing to parse the data from the response in a more dynamic way. If you do have control of the API, you should consider returning the data this way instead.

Marshal map[string] interface{} but with tags

I know Go has a way to json.Marshal struct and also json.Marshal map[string]interface{}.
But when it marshals a struct, it can uses its json tags'. Is there a way, in standard or with another library to json.Marshal a map[string]interface{} and to pass it the same options that would have been stored in a field tag for a struct?
Actually there is a way, a bit tricky, but still.
You have to create a struct from reflect package.
You iterate over each element in your map and for each of them you create a struct field :
fields = append(fields, reflect.StructField{
Name: ,
Type: ,
Tag: ,
})
You can set the tags to whatever you want, meaning you can set json values, like the omitempty one.
Then you have to create the struct itself :
s := reflect.New(reflect.StructOf(fields))
Then another iteration over your map will be needed, to fill the struct with values.
s.Elem().FieldByName(name).Set(WhateverValue)
Finally you can pass your struct to json.Marshall(s.Interface()).

How to get data as is from MongoDB and send it to an API as JSON in Golang

I am writing a Golang API at work which when called, gets data from two different MongoDB Collections and appends it into a struct, converts it to JSON, and stringified and sends to an API (Amazon SQS)
The problem is, defining the struct of the data receiving from MongoDB, while some of the fields are defined properly, some are varying
// IncentiveRule struct defines the structure of Incentive rule from Mongo
type IncentiveRule struct {
... Other vars
Rule Rule `bson:"rule" json:"rule"`
... Other vars
}
// Rule defines the struct for Rule Object inside an incentive rule
type Rule struct {
...
Rules interface{} `bson:"rules" json:"rules"`
RuleFilter RuleFilter `bson:"rule_filter" bson:"rule_filter"`
...
}
// RuleFilter ...
type RuleFilter struct {
Condition string `bson:"condition" json:"condition"`
Rules []interface{} `bson:"rules" json:"rules"`
}
While this works, the interface{} defined inside Rule struct is varying and while getting as BSON and decoding and re-encoding to JSON, instead of encoding as "fookey":"barvalue" in JSON, it is encoded as "Key":"fookey","Value":"barvalue", how to avoid this behavior and have it as "fookey":"barvalue"
If you use interface{}, the mongo-go driver is free to choose whatever implementation it sees fits for representing the results. Often it will choose bson.D to represent documents which is an ordered list of key-value pairs where a pair is a struct having a field for Key and a field for Value , so the Go value can preserve the field order.
If field order is not required / important, you may explicitly use bson.M instead of interface{} and []bson.M instead of []interface{}. bson.M is an unordered map, but it represents fields in the form of fieldName: fieldValue, which is exactly what you want.

Dynamic Type in Unmarshal

I currently having the following problem:
I get a []byte / string via websocket which looks like
eventname {"JSON": "data", "In": "different formats"}
I split the string by the whitespace between the eventname and the JSON data and, depending on the eventname, I want to json.Unmarshal() the JSON data into a specific type or a var of a specific type, to make sure its all type safe.
So I would probably have a map which holds all the possible eventnames and the corresponding type for the JSON data, but im not sure how I would save a type, maybe by reference or by the stringified name?
type EventTypeList map[string]*interface{}
or
type EventTypeList map[string]string
So I can lookup if the event is in the EventTypeList and then let the Unmarshal func parse the data into the type from the map.
So basicly instead of the specific type "SpecificData":
type SpecificData struct {
JSON string
In string
}
socketData := SpecificData{}
err := json.Unmarshal(jsonData, &socketData)
I want to dynamically create the socketData var by the type from the EventTypeList
socketData := [dynamically determine this Type from EventTypeList]{}
After I parsed the data into that type, I want to call all listeners for that event and give them the socketData with the right type, so they can work with the expected data.
But im really not sure how I would accomplish this, if this is even possible or if this is even the right way...
Thanks for any help!
Ok, after reasearching, I think what I wanted to achive is not possible, because the type needs to be know at compile time, as it has been mentioned here:
Golang: cast an interface to a typed variable dynamically
But I think I can just pass the raw JSON string to the listener callback and Unmarshal the data in that function where the type of the data is known.
Thanks for all contributions!

Removing a specific element from a json array in golang

I tried a few options but with no results. If anyone knows some kind of solution it would be nice. I was trying with buger/jsonparser because of the parsing speed. Lets say i want to exclude object3 and assign it to MYVARIABLE
for exaple :
data:=[{object1}, {object2}, {object3}]
//this function iterates through the array
jsonparser.ArrayEach(data, func(key []byte, dataType jsonparser.ValueType, offset int, err error) {
MYVARIABLE:=key
return
})
Let's say that you have successfully parsed your data to struct.
And you would have an array of yourStruct []yourStruct, and assign the third element with empty struct like this :
yourStruct[2] = YourStruct{}
the third element is still there with empty value. And unfortunately in go you can't assign struct with nil value.
or you can convert the []byte of your data that has your json to string and iterate it over to the their element and remove it with empty char, but this would be an expensive approach.
As Kaedys said you can remove your array struct using slice like this :
yourStruct = yourStruct[:2]
fmt.Printf("resutl struct = %+v\n", yourStruct)