Как упростить маршалинг глубоко вложенного JSON - PullRequest
0 голосов
/ 02 октября 2018

У меня есть JSON, который содержит некоторые статические и динамические данные.Ниже приведен пример JSON

{
  "request": {  /*Static data start */
    "data": {
      "object": { /*Static data ends here*/
        "user": { /*Dynamic data start here */
          "userid": "andmmdn",
          "ipaddr": "1.1.1.1",
          "noofusers": "100",
          "qos": "34",
          "id": "kldjflkdfjlkdjfkld",
          "domain": "xyz.com" /*Dynamic data ends here */
        } 
      }
    }
  }
}

Ниже приведен код, который может создать этот JSON

package main

import (
    "fmt"
    "encoding/json"
)
//ReqJSON struct
type ReqJSON struct {
    Request Request `json:"request"`
}
//Request struct
type Request struct {
    Data Data `json:"data"` 
}
//Data struct
type Data struct {
    Object Object `json:"object"`
}
//Object struct
type Object struct {
    User User `json:"user"`
}
//User struct
type User struct {
    UserID string `json:"userid"`
    IPAddr string `json:"ipaddr"`
    Noofusers string `json:"noofusers"`
    Qos string `json:"qos"`
    ID string `json:"id"`
    Domain string `json:"domain"`
}
func main() {
    test := ReqJSON {
        Request{
            Data: Data{
                Object: Object{
                    User: User{
                        UserID: "andmmdn",
                        IPAddr: "1.1.1.1",
                        Noofusers: "100",
                        Qos: "34",
                        ID: "kldjflkdfjlkdjfkld",
                        Domain: "xyz.com",
                    },  
                },  
            },
        },
    }
    jsonEncode, _ := json.Marshal(test)
    jsonIdent, _ := json.MarshalIndent(&test, "", "\t")
    fmt.Println(string(jsonEncode))
    fmt.Println(string(jsonIdent))
}

. Как видно из приведенного выше, он содержит структуру, которая не имеет большого смысла какони действуют больше как заполнитель для вложения данных.Так как мы делаем это более оптимизированным.Поскольку все данные обрабатываются в последней структуре.Какой подход должен использоваться для демаршалинга данных, поскольку ответ будет в том же формате, и вы захотите использовать последнюю структуру для того же.Любые мысли на подходе.Также, как сделать общую структуру как несколько API, которая использует ту же структуру, приведенную ниже, является примером

//ReqJSON for populating data
type ReqJSON struct {
    Request struct {
        Data struct {
            Object struct {
                Auth Auth `json:"auth"`
            } `json:"object"`
        } `json:"data"`
    } `json:"request"`
}
//ReqJSON for populating data
type ReqJSON struct {
    Request struct {
        Data struct {
            Object struct {
                Error Error `json:"error"`
            } `json:"object"`
        } `json:"data"`
    } `json:"request"`
}

Ответы [ 3 ]

0 голосов
/ 02 октября 2018

Вы не можете устранить сложность, но вы можете потенциально скрыть некоторые из них внутри пользовательского Marshaler:

type Request struct {
    UserID    string `json:"userid"`
    IPAddr    string `json:"ipaddr"`
    Noofusers string `json:"noofusers"`
    Qos       string `json:"qos"`
    ID        string `json:"id"`
    Domain    string `json:"domain"`
}

func (r *Request) MarshalJSON() ([]byte, error) {
    type request struct {
        Data struct {
            Object struct {
                User struct {
                    Request
                } `json:"user"`
            } `json:"object"`
        } `json:"data"`
    }
    structure := request{Data: data{Object: object{User: user{r}}}}
    return json.Marshal(structure)    
}

Тот же самый подход может быть использован в обратном порядке для UnmarshalJSON, если это необходимо.

0 голосов
/ 02 октября 2018

Если вам не нужны типы оберток для чего-либо, кроме маршалинга / демаршалинга, вы можете определить их анонимно:

type ReqJSON struct {
    Request struct {
        Data struct {
            Object struct {
                User User `json:"user"`
            } `json:"object"`
        } `json:"data"`
    } `json:"request"`
}

type User struct {
    UserID string `json:"userid"`
    IPAddr string `json:"ipaddr"`
    Noofusers string `json:"noofusers"`
    Qos string `json:"qos"`
    ID string `json:"id"`
    Domain string `json:"domain"`
}

И, исходя из ответа icza, вы можете добавить методы доступа к ReqJSON:

func (j *ReqJSON) User() User     { return j.Request.Data.Object.User }
func (j *ReqJSON) SetUser(u User) { j.Request.Data.Object.User = u }

func main() {
    var j ReqJSON
    j.SetUser(User{
            UserID:    "_id",
            IPAddr:    "1.1.1.1",
            Noofusers: "100",
            Qos:       "34",
            ID:        "kldjflkdfjlkdjfkld",
            Domain:    "xyz.com",
    })

    b, err := json.MarshalIndent(j, "", "  ")
    fmt.Println(err, string(b))
}
0 голосов
/ 02 октября 2018

Звучит примерно так.Решение немного многословно / избыточно, но так же и формат данных, с которым вам приходится иметь дело.

Чтобы работать с этим легко, вы можете создавать вспомогательные функции и использовать их:

func wrap(u User) *ReqJSON {
    return &ReqJSON{Request: Request{Data: Data{Object: Object{User: u}}}}
}

func unwrap(r *ReqJSON) User {
    return r.Request.Data.Object.User
}

Но кроме этого, вы не можете реально упростить другие вещи.

Таким образом, маршалинг User подобен:

var u User
data, err := json.Marshal(wrap(u))

Unmarshaling:

var r *ReqJSON
err := json.Unmarshal(data, &r)
// Check error

u := unwrap(r) // Here we have the user
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...