How to convert Json string to xml in Golang? - json

I'm trying to convert json string in to xml format using Golang. My whole object is to convert json in to map string interface and then convert interface in to xml file. (There is no predefined structs). Please help me to solve this issue?
var f interface{}
err := json.Unmarshal(b, &f)

There's an xml package that is equivalent to the json one under encoding. Just import it and then marshal the result of your json.Unmarshal
import "encoding/xml"
xml.Marshal(&f)

Related

Equivalent of PHP json_decode in Golang

Equivalent of PHP json_decode in Golang
Thanks to the following references :
PHP Manual : json_decode — Decodes a JSON string
php2golang : GoLang alternatives for PHP functions
A Guide to JSON in Golang
To convert JSON data (strings or bytes) into Go types like structs, arrays, and slices, as well as unstructured data like maps and empty interfaces.
..
If you don’t know the structure of your JSON properties beforehand, you cannot use structs to unmarshal your data ..
Looking for an equivalent of PHP json_decode in Golang I go immediately to : Decoding JSON to Maps - Unstructured Data
With the code below :
package main
import (
"fmt"
"os"
"encoding/json"
)
func main() {
json := `{"key_0":{"key_1":"value_1","key_2":"value_2"},"key_3":"value_3"}`
json_decoded, err := Json_decode(json)
fmt.Println(json_decoded)
fmt.Println(json_decoded["key_0"])
return
}
func Json_decode(data string) (map[string]interface{}, error) {
var dat map[string]interface{}
err := json.Unmarshal([]byte(data), &dat)
return dat, err
}
We got this output :
map[key_0:map[key_1:value_1 key_2:value_2] key_3:value_3]
map[key_1:value_1 key_2:value_2]
If we add this line :
fmt.Println(json_decoded["key_0"]["key_1"])
We got this error :
invalid operation: json_decoded["key_0"]["key_1"] (type interface {} does not support indexing)
To get value_1 we have to add these lines :
key_0 := json_decoded["key_0"].(map[string]interface{})
fmt.Println(key_0["key_1"])
But we don’t know the structure of the JSON
Lets say the JSON is a PHP array encoded with json_encode
The key can either be an int or a string and the value can be of any type.
So we may have to add these lines :
key_0 := json_decoded["key_0"].([]interface{})
fmt.Println(key_0[O])
Looking for an equivalent of PHP json_decode in Golang what do you suggest ?
encoding/json requires you to know your data structures,
you can use map[string]interface{} but it will be very slow and hard to manage.
package main
import (
//"encoding/json"
"jsonparser"
)
Alternative JSON parser for Go (10x times faster standard library)

Get JSON representation of request body as a string

I would like to take an arbitrary http.Request and get the body as a json string. I know this involves the json package, but it seems json.Decode needs a specific struct passed in by reference. How can I decode an arbitrary request body (and then stringify the result)?
func RequestBodyJsonString(r *http.Request) string {
}
Use ioutil.ReadAll to get data in byte slice then type conversion to string to get json string
bytedata, err := ioutil.ReadAll(r.Body)
reqBodyString := string(data)
An example in go playground here

Passing interfaces into functions

I'm trying to write a configuration package that takes a json filename and a configuration struct. It should unmarshal the json into the passed-in struct and return it. I'm trying to work with interfaces so I can pass any struct I want
The error is:
panic: interface conversion: interface {} is map[string]interface {}, not *main.ConfigurationData
I'm not quite sure how to solve this issue.
Here is my main package
package main
import (
"config"
"commons"
)
type ConfigurationData struct {
S3ARN string `json:"S3ARN"`
SQSQueueUrl string `json:"SQSQueueUrl"`
}
var configData *ConfigurationData
func main(){
configData=config.Load("aws.config.json",configData).(*ConfigurationData)
commons.Dump(configData)
}
Here is my config package
package config
import (
"os"
"encoding/json"
"sync"
"commons"
)
var configLock = new(sync.RWMutex)
func Load(filename string,config interface{})interface{} {
file, err := os.Open(filename)
commons.CheckErrorf(err, "Config Open Error")
defer file.Close()
decoder := json.NewDecoder(file)
configLock.Lock()
err = decoder.Decode(&config)
commons.CheckErrorf(err, "Config Decode Error")
configLock.Unlock()
return config
}
This answer explains well why you get the exception.
What you should do:
When the encoding/json package runs into a type that implements the Marshaler interface, it uses that type’s MarshalJSON() method instead of the default marshaling code to turn the object into JSON. Similarly, when decoding a JSON object it will test to see if the object implements the Unmarshaler interface, and if so it will use the UnmarshalJSON() method instead of the default unmarshaling behavior.
Mine solution for this would be to implement UnmarshalJSON method on *ConfigurationData and method Load should accept Unmarshaler interface instead of interface{}.
You can read more about technics here: https://blog.gopheracademy.com/advent-2016/advanced-encoding-decoding/
Then you simple would do json.Unmarshal(b, &config) inside the Load method where b is []byte read from file.
According to the documentation on json.Unmarshall unmarshalling into an interface value will unmarshall to a new struct of one of a predefined list of types:
To unmarshal JSON into an interface value, Unmarshal stores one of
these in the interface value:
bool, for JSON booleans
float64, for JSON numbers
string, for JSON
strings []interface{}, for JSON arrays
map[string]interface{}, for JSON objects
nil for JSON null
In your case, the type that was chosen was map[string]interface{}. Within your function, a pointer to that newly unmarshalled struct is stored in the config parameter and returned. The panic occurs as the type of the value returned is not the type you're asserting it is.

ASCII to Json in go

im kinda new to programming but i found that python didnt have the speed i needed so i switched to go, im building a scraper and i need to convert a what looks like to be a ASCII formated string to json but i cant find any good documentation on how to do this in go.
the string i need converted looks something like this: debug%22%3Afalse%2C%22pageOpts%22%3A%7B%22noBidIfUnsold%22%3Atrue%2C%22keywords%22%3A%7B%22no-sno-finn-object_type%22%3A%22private%22%2C%22no-sno-finn-car_make%22%3A%22796%22%2C%22aa-sch-publisher%22%3A%22finn%22%2C%22aa-sch-inventory_type%22%3A%22classified%22%2C%22aa-sch-country_code%22%3A%22no%22%2C%22no-sno-finn-section%22%3A%22car%22%2C%22no-sno-finn-ad_owner%22%3A%22false%22%2C%22no-sno-publishergroup%22%3A%22schibsted%22%2C%22aa-sch-supply_type%22%3A%22web_desktop%22%2C%22no-sno-finn-subsection%22%3A%22car_used%22%2C%22aa-sch-page_type%22%3A%22object%22%7D
Thanks in advance!
As mentioned by a commenter, your string is URL encoded and can be decoded using url.QueryUnescape(...):
package main
import (
"fmt"
"net/url"
)
func main() {
querystr := "debug%22%3Afalse%2C%22pageOpts%22%3A%7B%22noBidIfUnsold%22%3Atrue%2C%22keywords%22%3A%7B%22no-sno-finn-object_type%22%3A%22private%22%2C%22no-sno-finn-car_make%22%3A%22796%22%2C%22aa-sch-publisher%22%3A%22finn%22%2C%22aa-sch-inventory_type%22%3A%22classified%22%2C%22aa-sch-country_code%22%3A%22no%22%2C%22no-sno-finn-section%22%3A%22car%22%2C%22no-sno-finn-ad_owner%22%3A%22false%22%2C%22no-sno-publishergroup%22%3A%22schibsted%22%2C%22aa-sch-supply_type%22%3A%22web_desktop%22%2C%22no-sno-finn-subsection%22%3A%22car_used%22%2C%22aa-sch-page_type%22%3A%22object%22%7D"
// Parse the URL encoded string.
plainstr, err := url.QueryUnescape(querystr)
if err != nil {
panic(err)
}
fmt.Println(plainstr)
// debug":false,"pageOpts":{"noBidIfUnsold":true,"keywords":{"no-sno-finn-object_type":"private","no-sno-finn-car_make":"796","aa-sch-publisher":"finn","aa-sch-inventory_type":"classified","aa-sch-country_code":"no","no-sno-finn-section":"car","no-sno-finn-ad_owner":"false","no-sno-publishergroup":"schibsted","aa-sch-supply_type":"web_desktop","no-sno-finn-subsection":"car_used","aa-sch-page_type":"object"}
}
Your example string appears to be incomplete but eventually it can be decoded into a struct or map using json.Unmarshal(...).

How can we read a json file as json object in golang

I have a JSON file stored on the local machine. I need to read it in a variable and loop through it to fetch the JSON object values. If I use the Marshal command after reading the file using the ioutil.Readfile method, it gives some numbers as an output. These are my few failed attempts,
Attempt 1:
plan, _ := ioutil.ReadFile(filename) // filename is the JSON file to read
var data interface{}
err := json.Unmarshal(plan, data)
if err != nil {
log.Error("Cannot unmarshal the json ", err)
}
fmt.Println(data)
It gave me following error,
time="2016-12-13T22:13:05-08:00" level=error msg="Cannot unmarshal the json json: Unmarshal(nil)"
<nil>
Attempt 2: I tried to store the JSON values in a struct and then using MarshalIndent
generatePlan, _ := json.MarshalIndent(plan, "", " ") // plan is a pointer to a struct
fmt.Println(string(generatePlan))
It give me the output as string. But if I cast the output to string then I won't be able to loop it as JSON object.
How can we read a JSON file as JSON object in golang? Is it possible to do that?
Any help is appreciated. Thanks in advance!
The value to be populated by json.Unmarshal needs to be a pointer.
From GoDoc :
Unmarshal parses the JSON-encoded data and stores the result in the value pointed to by v.
So you need to do the following :
plan, _ := ioutil.ReadFile(filename)
var data interface{}
err := json.Unmarshal(plan, &data)
Your error (Unmarshal(nil)) indicates that there was some problem in reading the file , please check the error returned by ioutil.ReadFile
Also please note that when using an empty interface in unmarshal, you would need to use type assertion to get the underlying values as go primitive types.
To unmarshal JSON into an interface value, Unmarshal stores one of
these in the interface value:
bool, for JSON booleans
float64, for JSON numbers
string, for JSON strings
[]interface{}, for JSON arrays
map[string]interface{}, for JSON objects
nil for JSON null
It is always a much better approach to use a concrete structure to populate your json using Unmarshal.
If you're looking at this in 2022, the ioutil package has been deprecated. You can still use it but you'll get annoying errors.
Instead you can use the os package.
someStruct := SomeStruct{} // Read errors caught by unmarshal
fileBytes, _ := os.ReadFile(filename)
err := json.Unmarshal(fileBytes, spec)
Note, I'm specifically ignoring the error from os.ReadFile since it will also cause an error in json.Unmarshal for the sake of the example.