XML to Json
package main
import (
"encoding/json"
"encoding/xml"
"fmt"
)
type Persons struct {
Person []struct {
Name string
Age int
}
}
type Places struct {
Place []struct {
Name string
Country string
}
}
type Parks struct {
Park struct {
Name []string
Capacity []int
}
}
const personXml = `
<Persons>
<Person><Name>Koti</Name><Age>30</Age></Person>
<Person><Name>Kanna</Name><Age>29</Age></Person>
</Persons>
`
const placeXml = `
<Places>
<Place><Name>Chennai</Name><Country>India</Country></Place>
<Place><Name>London</Name><Country>UK</Country></Place>
</Places>
`
const parkXml = `
<Parks>
<Park><Name>National Park</Name><Capacity>10000</Capacity></Park>
<Park>Asian Park</Name><Capacity>20000</Capacity></Park>
</Parks>
`
func WhatIamUsing() {
var persons Persons
xml.Unmarshal([]byte(personXml), &persons)
per, _ := json.Marshal(persons)
fmt.Printf("%s\n", per)
var places Places
xml.Unmarshal([]byte(placeXml), &places)
pla, _ := json.Marshal(places)
fmt.Printf("%s\n", pla)
var parks Parks
xml.Unmarshal([]byte(parkXml), &parks)
par, _ := json.Marshal(parks)
fmt.Printf("%s\n", par)
}
What i want is a generic function which takes xml string and dataStruct and returns a Json output. But below function is throwing an error How to impliment this?
func Xml2Json(xmlString string, DataStruct interface{}) (jsobj string, err error) {
var dataStruct DataStruct
xml.Unmarshal([]byte(personXml), &dataStruct)
js, _ := json.Marshal(dataStruct)
return fmt.Sprintf("%s\n", js), nil
}
func main() {
jsonstring, _ := Xml2Json(personXml, Persons)
}
Error message:
prog.go:73: DataStruct is not a type
prog.go:80: type Persons is not an expression
goplay link: http://play.golang.org/p/vayb0bawKx
Each data field in a struct is declared with a known type, which could be a built-in type or another user-defined type. Structs are the only way to create concrete user-defined types in Golang. Struct types are declared by composing a fixed set of unique fields.
And pass by reference is when we pass the parameter with a pointer to the given parameter. In Golang, we can see these two in this example below. Actually, there are already many examples of how to do pass by reference and pass by value in Golang that we can find on the Internet.
One solution would be to create an interface and a greeting method. type Greetable interface { Greeting () string Name () string } You would then implement the Greeting and Name methods in your struct (this would immediately implement the Greetable interface, due to the way that Go handles interfaces ):
There is a generic function that will accept interface {} and do something inside it. And it supports many structs. The snippet code would be like this: This one is really-really a serious thing in Golang. We must very careful when working with pass-by-reference and interface {}.
You can not store a type (like Persons
) in an interface. You could pass a reflect.Type
to your function. Then, your call would look like Xml2Json(personXml, reflect.TypeOf(Persons))
which is quite ugly in my opinion.
The better approach is probably:
func Xml2Json(xmlString string, value interface{}) (string, error) {
if err := xml.Unmarshal([]byte(xmlString), value); err != nil {
return "", err
}
js, err := json.Marshal(value)
if err != nil {
return "", err
}
return string(js), nil
}
You can use this function with Xml2Json(personXml, new(Persons))
if you are not interested in the value itself, and
var persons Persons
Xml2Json(personXML, &persons)
when you also want to retrieve the struct value for later processing.
The function Xml2Json
declares a parameter named DataStruct
. In the same scope the identifier DataStruct
cannot denote a type name. If you want to use the type name DataStruct
within the same scope, you must name your parameter differently.
In the main function the problem is that a function call syntax expects an expression list within the parenthesis. There you're passing a type name, which clearly cannot be an expression.
So to answer your question: No, you cannot pass a type as an argument to a function. But you can pass an instance of a type (in this case a pointer to such instance) to get the effect you're about:
package main
import (
"encoding/json"
"encoding/xml"
"fmt"
"log"
)
type Persons struct {
Person []struct {
Name string
Age int
}
}
type Places struct {
Place []struct {
Name string
Country string
}
}
type Parks struct {
Park struct {
Name []string
Capacity []int
}
}
const (
personXml = `
<Persons>
<Person><Name>Koti</Name><Age>30</Age></Person>
<Person><Name>Kanna</Name><Age>29</Age></Person>
</Persons>
`
placeXml = `
<Places>
<Place><Name>Chennai</Name><Country>India</Country></Place>
<Place><Name>London</Name><Country>UK</Country></Place>
</Places>
`
parkXml = `
<Parks>
<Park><Name>National Park</Name><Capacity>10000</Capacity></Park>
<Park><Name>Asian Park</Name><Capacity>20000</Capacity></Park>
</Parks>
`
)
func Xml2Json(xmlString string, DataStruct interface{}) (jsobj string, err error) {
if err = xml.Unmarshal([]byte(xmlString), DataStruct); err != nil {
return
}
js, err := json.Marshal(DataStruct)
if err != nil {
return
}
return fmt.Sprintf("%s", js), nil
}
func main() {
var p Persons
jsonstring, err := Xml2Json(personXml, &p)
if err != nil {
log.Fatal(err)
}
fmt.Println(jsonstring)
var q Places
jsonstring, err = Xml2Json(placeXml, &q)
if err != nil {
log.Fatal(err)
}
fmt.Println(jsonstring)
var r Parks
jsonstring, err = Xml2Json(parkXml, &r)
if err != nil {
log.Fatal(err)
}
fmt.Println(jsonstring)
}
Playground
Output:
{"Person":[{"Name":"Koti","Age":30},{"Name":"Kanna","Age":29}]}
{"Place":[{"Name":"Chennai","Country":"India"},{"Name":"London","Country":"UK"}]}
{"Park":{"Name":["National Park","Asian Park"],"Capacity":[10000,20000]}}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With