Try it yourself with our free Xml Formatter tool — runs entirely in your browser, no signup needed.

How to Convert XML to JSON in Go

How to convert XML to JSON in Go

Converting XML to JSON is a common task in software development, especially when working with APIs or data exchange formats. Go, also known as Golang, is a popular programming language that provides a robust standard library and a vibrant ecosystem of third-party packages. In this article, we will explore how to convert XML to JSON in Go, covering the basics, handling edge cases, and providing performance tips.

Quick Example

Here is a minimal example that converts an XML string to a JSON string:

package main

import (
	"encoding/json"
	"encoding/xml"
	"fmt"
)

type Person struct {
	Name  string `xml:"name" json:"name"`
	Email string `xml:"email" json:"email"`
}

func main() {
	xmlStr := `
		<person>
			<name>John Doe</name>
			<email>johndoe@example.com</email>
		</person>
	`

	var person Person
	err := xml.Unmarshal([]byte(xmlStr), &person)
	if err != nil {
		fmt.Println(err)
		return
	}

	jsonStr, err := json.Marshal(person)
	if err != nil {
		fmt.Println(err)
		return
	}

	fmt.Println(string(jsonStr))
}

This code defines a Person struct with XML and JSON tags, unmarshals the XML string into the struct, and then marshals the struct into a JSON string.

Step-by-Step Breakdown

Let's walk through the code line by line:

  • package main: The package declaration is required for any Go program.
  • import: We import the encoding/json and encoding/xml packages, which provide functions for encoding and decoding JSON and XML data.
  • type Person struct { ... }: We define a Person struct with two fields: Name and Email. The XML and JSON tags specify how the fields should be serialized and deserialized.
  • func main() { ... }: The main function is the entry point of the program.
  • xmlStr := ...: We define an XML string that contains a single person element with name and email elements.
  • var person Person: We declare a person variable of type Person.
  • err := xml.Unmarshal([]byte(xmlStr), &person): We use the xml.Unmarshal function to deserialize the XML string into the person struct. The []byte(xmlStr) conversion is required because Unmarshal expects a byte slice.
  • if err != nil { ... }: We check if the unmarshaling process failed and print an error message if it did.
  • jsonStr, err := json.Marshal(person): We use the json.Marshal function to serialize the person struct into a JSON string.
  • if err != nil { ... }: We check if the marshaling process failed and print an error message if it did.
  • fmt.Println(string(jsonStr)): We print the resulting JSON string.

Handling Edge Cases

Here are some common edge cases to consider:

Empty/null input

If the input XML string is empty or null, the xml.Unmarshal function will return an error. You can handle this case by checking the error value:

xmlStr := ""
var person Person
err := xml.Unmarshal([]byte(xmlStr), &person)
if err != nil {
    if err == io.ErrUnexpectedEOF {
        fmt.Println("Input XML is empty")
    } else {
        fmt.Println(err)
    }
    return
}

Invalid input

If the input XML string is invalid (e.g., malformed or missing closing tags), the xml.Unmarshal function will return an error. You can handle this case by checking the error value:

xmlStr := "<person><name>John</name>"
var person Person
err := xml.Unmarshal([]byte(xmlStr), &person)
if err != nil {
    fmt.Println(err)
    return
}

Large input

If the input XML string is very large, you may need to use a streaming XML parser to avoid running out of memory. The encoding/xml package provides a Decoder type that can be used for streaming XML parsing:

xmlStr := strings.Repeat("<person><name>John</name></person>", 100000)
decoder := xml.NewDecoder(strings.NewReader(xmlStr))
var person Person
for {
    token, err := decoder.Token()
    if err != nil {
        if err == io.EOF {
            break
        }
        fmt.Println(err)
        return
    }
    switch token := token.(type) {
    case xml.StartElement:
        if token.Name.Local == "person" {
            err := decoder.DecodeElement(&person, &token)
            if err != nil {
                fmt.Println(err)
                return
            }
        }
    }
}

Unicode/special characters

If the input XML string contains Unicode or special characters, you may need to use a Unicode-aware XML parser. The encoding/xml package provides a Decoder type that can be used for Unicode-aware XML parsing:

xmlStr := "<person><name>John Doe</name><email>johndoe@example.com</email></person>"
decoder := xml.NewDecoder(strings.NewReader(xmlStr))
decoder.CharsetReader = func(charset string, input io.Reader) (io.Reader, error) {
    if charset == "UTF-16" {
        return unicode.UTF16(unicode.LittleEndian, input), nil
    }
    return input, nil
}
var person Person
err := decoder.Decode(&person)
if err != nil {
    fmt.Println(err)
    return
}

Common Mistakes

Here are some common mistakes to avoid:

  • Not checking errors: Always check the error values returned by xml.Unmarshal and json.Marshal.
  • Not using XML tags: If you don't use XML tags on your struct fields, the xml.Unmarshal function will not be able to deserialize the XML data correctly.
  • Not handling edge cases: Always handle edge cases such as empty/null input, invalid input, and large input.

Performance Tips

Here are some performance tips for converting XML to JSON in Go:

  • Use a streaming XML parser: If you need to parse large XML files, use a streaming XML parser to avoid running out of memory.
  • Use a JSON encoder with a buffer: If you need to marshal a large amount of JSON data, use a JSON encoder with a buffer to avoid creating a large string.
  • Avoid unnecessary allocations: Avoid unnecessary allocations by reusing buffers and slices.

FAQ

Q: How do I convert XML to JSON in Go?

A: You can use the encoding/xml and encoding/json packages to convert XML to JSON in Go.

Q: What is the difference between xml.Unmarshal and json.Marshal?

A: xml.Unmarshal deserializes XML data into a Go struct, while json.Marshal serializes a Go struct into JSON data.

Q: How do I handle empty/null input XML?

A: You can check the error value returned by xml.Unmarshal and handle the case where the input XML is empty or null.

Q: How do I handle invalid input XML?

A: You can check the error value returned by xml.Unmarshal and handle the case where the input XML is invalid.

Q: How do I handle large input XML?

A: You can use a streaming XML parser to avoid running out of memory.

AI agent tools available. The CodeTidy MCP Server gives Claude, Cursor, and other AI agents access to 60+ developer tools. One command: npx @codetidy/mcp