0

I am new to Go but have been impressed with the speed and low resource consumption when processing multi-GB XML so I am trying to use it to convert a large XML file to JSON.

This in itself seems relatively simple. However I also need to JSONify the field names in the JSON output.

I hit on the idea of having an identical struct, but with the JSONified field names and copying from the struct that I unmarshall the XML to, into my new struct.

I have tried something similar to the following:

package main

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

var data = []byte(`
    <Products xmlns="">
        <SupplierName>AcmeCorp</SupplierName>
        <Id>33</Id>
        <MaxValue>34500.01</MaxValue>
        <SupplierContact>
            <Name>Bob and Alice</Name>
            <Address1>Acme Corp Ltd 
PO Box 999, 
Nottingham,
NG1 1AA</Address1>
        </SupplierContact>
    </Products>
`)

type XMLProducts struct {
    SupplierName    string
    Id              int
    MaxValue        float32
    SupplierContact struct {
        Name     string
        Address1 string
    }

    // Another 50 elements including more nested structs

}

type JSONProducts struct {
    supplierName    string 
    id              int
    maxValue        float32
    supplierContact struct {
        name     string
        address1 string
    }
}

func main() {
    buf := bytes.NewBuffer(data)
    dec := xml.NewDecoder(buf)

    var p XMLProducts
    err := dec.Decode(&p)
    check2(err)

    var j JSONProducts

    j.supplierName = p.SupplierName
    j.id = p.Id
    j.maxValue = p.MaxValue
    j.supplierContact.name = p.SupplierContact.Name
    j.supplierContact.address1 = p.SupplierContact.Address1

    jsonBytes, err := json.Marshal(p)
    check2(err)

    myJSON := string(jsonBytes) + "\n"

    fmt.Println(myJSON)

    jsonBytes2, err := json.Marshal(j)
    check2(err)

    myJSON2 := string(jsonBytes2) + "\n"

    fmt.Println(myJSON2)

}

func check2(err error) {
    if err != nil {
        panic(err)
    }
}

However when I run this code, jsonBytes2 and consequently myJSON2 is empty!

What have I done wrong and what change do I need to make to correctly populate myJSON2 with the values from myJSON?

Also, am I going about this in a sensible way or is there a better way of doing this?

https://play.golang.org/p/U0HrcgQe4XN

Nigel Ainscoe
  • 185
  • 1
  • 3
  • 14
  • You must export struct field names, start their name with a capital letter: [Go Playground](https://play.golang.org/p/zF7Wkyxw4jq). – icza Jan 15 '20 at 12:59
  • @icza Thank you for your quick reply. However the whole point is that I need to change that casing. JSON variables typically start with a lowercase (and have to be in this case because the consuming app expects as much) so my task is to convert the XML field names. Maybe I will have to resort to a string replace. – Nigel Ainscoe Jan 15 '20 at 13:22
  • The `encoding/json` package requires fields to be uppercased, but you may use struct tags to map how those fields appear in JSON. You may map them to lowercased names or something entirely different. See [What are the use(s) for tags in Go?](https://stackoverflow.com/questions/10858787/what-are-the-uses-for-tags-in-go/30889373#30889373) See example on the [Go Playground](https://play.golang.org/p/WuvEuyG4N_r). – icza Jan 15 '20 at 13:24
  • @icza That looks like the solution to me. Thanks a lot. – Nigel Ainscoe Jan 15 '20 at 13:31

0 Answers0