go json data forwarding

Posted by sampledformat on Sun, 06 Oct 2019 05:29:57 +0200

case

For example, there is a GET interface that allows batch access to user information (1)

> curl 'http://localhost:8080/user/1,2,3'
[
    {
        "user_id":1,
        "other_suff":...
    },
    {
        "user_id":2,
        "other_suff":...
    },
    {
        "user_id":3,
        "other_suff":...
    }
]

At the same time, we need to put user information and some of their order information together and assemble them into (1) interfaces to meet other business needs.

[
    {
        "user_info":{
            "user_id":1,
            "other_suff":...
        },
        "order_info":{
            "order_id":1,
            "user_id":1,
            "other_suff":...
        }
    },
    {
        "user_info":{
            "user_id":2,
            "other_suff":...
        },
        "order_info":{
            "order_id":2,
            "user_id":2,
            "other_suff":...
        }
    },
    {
        "user_info":{
            "user_id":3,
            "other_suff":...
        },
        "order_info":{
            "order_id":3,
            "user_id":3,
            "other_suff":...
        }
    }
]

Analysis

The solution to this problem is simple: json of user information and order information is parsed to get the structure with tools, and then their interfaces are called to get the data, which is correlated and assembled according to id, and finally returned.

One problem with this approach is that the code parses the complete structure of user and order. If the user information returned by user interface adds fields, the structure here should be updated synchronously, otherwise the data we give is incomplete. (This can be painful. You ask other teams to add fields and have to schedule...

In fact, as the "middleman" of data, we only care about user_id in user interface json, which we use to associate order data. We don't care about other_suff or other data in user information, as long as it's guaranteed to be sent out completely.

according to https://golang.org/pkg/encodi... As you can see, throwing a map[string]interface {} directly to json.Unmarshal can also be parsed properly, so we can write more general passband code.

type Content []map[string]interface{}

func (c Content) GetByFieldName(name string, defaultVal interface{}) infterface{} {
    for _, item := range c {
        val, ok := item[name]
        if !ok {
            continue
        }
        if val == nil {
            return defaultVal
        }
        return val
    }
    return defaultVal
}

func getUserContentByIDs(ids []int) Content {
    ...
    var c Content
    err := json.Unmarshal(jsonData, &c) 
    ...
    return c
}

func getOrderContentByUserIDs(ids []int) Content {.../*Ditto*/}

func Handler(userIDs []int) []Combine {

    users := getUserContentByIDs(userIDs)
    orders := getOrderContentByUserIDs(userIDs)

    // This assumes a one-to-one relationship between the user and the order.
    ret := make([]Combine, 0, len(users))
    for _, u := range users {
        for _, o := range orders {
            userID := u.GetByFieldName("user_id", 0) 
            orderUserID := o.GetByFieldName("user_id", 0)
            if userID != 0 && userID == orderUserID {
                ret = append(ret, Combine{
                    UserInfo:  u,
                    OrderInfo: o,
                })
                break
            }
        }
    }
    return ret
}

P.S. In the example above, each query for Content traverses the array. If the amount of data is large or the query is frequent, the query efficiency can be improved by encapsulating a map for Content according to the unique label of item when initializing Content.

Topics: Go JSON curl