0

I combined some properties common to all objects into a struct.

type Document struct {
    ID        string    `json:"_id,omitempty"`
    UpdatedAt time.Time `json:"updatedat"`
    CreatedAt time.Time `json:"createdat"`
}

I also have an address struct, which is not a document.

type Address struct {
    AddressLine string `json:"addressline,omitempty"`
    City        string `json:"city,omitempty"`
    Country     string `json:"country,omitempty"`
    CityCode    int    `json:"citycode,omitempty"`
}

My customer struct is a document. It also has an address property.

type Customer struct {
    Document `json:"document"`
    Address  Address `json:"address"`
    Name     string  `json:"name,omitempty"`
    Email    string  `json:"email,omitempty"`
    Valid    bool    `json:"valid,omitempty"`
}

The JSON object from MongoDB is as follows;

[
    {
        "_id": "6186b4556971a9dbae117333",
        "address": {
            "addressline": "Foo Address",
            "city": "Foo City",
            "citycode": 0,
            "country": "Foo Country"
        },
        "document": {
            "createdat": "0001-01-01T03:00:00+03:00",
            "updatedat": "0001-01-01T03:00:00+03:00"
        },
        "email": "[email protected]",
        "name": "Foo Fooster",
        "valid": false
    }
]

I am using the following code to unmarshal this.

    var customerEntity Entities.Customer
    json.Unmarshal(customerEntityBytes, &customerEntity)

But all I can get is the following line. Most fields are empty.

{{ 0001-01-01 00:00:00 +0000 UTC 0001-01-01 00:00:00 +0000 UTC} {   0}   false}

As I thought this was due to the mixed nested structure, I created another customer struct for testing purposes;

import "time"

type AutoGenerated []struct {
    ID      string `json:"_id"`
    Address struct {
        Addressline string `json:"addressline"`
        City        string `json:"city"`
        Citycode    int    `json:"citycode"`
        Country     string `json:"country"`
    } `json:"address"`
    Document struct {
        Createdat time.Time `json:"createdat"`
        Updatedat time.Time `json:"updatedat"`
    } `json:"document"`
    Email string `json:"email"`
    Name  string `json:"name"`
    Valid bool   `json:"valid"`
}

All of a sudden the whole problem was fixed and I was able to access it with all fields filled.

In summary, I cannot unmarshal the Custumer struct I want to use. Do I need to override the unmarshall method for this? I've also reviewed the override examples but the codes are very subjective. A change I will make in base classes will cause me to change the unmarshall method. What is the clean way to this?

3
  • 2
    The JSON you got from mongo db is an array containing the desired object ([ {...} ]), therefore you must pass in a slice of customers to get it properly unmarshaled. i.e. var v []Entities.Customer; json.Unmarshal(data, &v); and then fmt.Println(v[0]). Commented Nov 6, 2021 at 18:49
  • It worked, thanks. But I still can't get the id value. Do you have an idea about it? Commented Nov 6, 2021 at 19:02
  • 1
    In the json _id is not nested withing document so you need a different type, one that reflects that "nestedness". play.golang.org/p/PkhBhVNGINi Commented Nov 6, 2021 at 19:08

1 Answer 1

3

Always check errors.

err = json.Unmarshal(customerEntityBytes, &customerEntity)
if err != nil {
    // json: cannot unmarshal array into Go value of type Entities.Customer
}

and the reason is, as @mkopriva pointed out - your JSON is an array - and you are unmarshaling to a single struct. To fix:

 var customerEntity []Entities.Customer // use slice to capture JSON array
 err = json.Unmarshal(customerEntityBytes, &customerEntity)
 if err != nil { /* ... */ }

You can certainly use your custom types, but you are losing the _id tag by nesting it in your Document struct. To fix, promote it to Customer:

type Document struct {
    //ID        string    `json:"_id,omitempty"`
    UpdatedAt time.Time `json:"updatedat"`
    CreatedAt time.Time `json:"createdat"`
}

type Customer struct {
    ID       string `json:"_id,omitempty"`
    
    // ...
}

Working example: https://play.golang.org/p/EMcC0d1xOLf

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.