加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

有没有更简单的方法使用Golang JSON编码在JSON对象上添加图层?

发布时间:2020-12-16 09:26:17 所属栏目:大数据 来源:网络整理
导读:Go中开箱即用的 JSON编码非常好,但我需要通过添加图层来使输出与特定格式匹配.我已经找到了一种方法,但希望有一种比我正在做的方式更简单的方法. 下面是我如何做的一个例子. import ( "bytes" "encoding/json" "encoding/xml" "fmt")type Query struct { XML
Go中开箱即用的 JSON编码非常好,但我需要通过添加图层来使输出与特定格式匹配.我已经找到了一种方法,但希望有一种比我正在做的方式更简单的方法.

下面是我如何做的一个例子.

import (
  "bytes"
  "encoding/json"
  "encoding/xml"
  "fmt"
)
type Query struct {
    XMLName xml.Name      `xml:"http://marklogic.com/appservices/search query" json:"-"`
    Format  int           `xml:"-" json:"-"`
    Queries []interface{} `xml:",any" json:"queries"`
}
type TermQuery struct {
    XMLName xml.Name `xml:"http://marklogic.com/appservices/search term-query" json:"-"`
    Terms   []string `xml:"http://marklogic.com/appservices/search text" json:"text"`
    Weight  float64  `xml:"http://marklogic.com/appservices/search weight,omitempty" json:"weight,omitempty"`
}
// use fakeQuery to avoid an infinite loop
type fakeQuery Query

//MarshalJSON for Query struct in a special way to add wraping {"query":...}
func (q Query) MarshalJSON() ([]byte,error) {
    return wrapJSON(`query`,fakeQuery(q))
}
// use fakeTermQuery to avoid an infinite loop
type fakeTermQuery TermQuery

//MarshalJSON for TermQuery struct in a special way to add wraping {"term-query":...}
func (q TermQuery) MarshalJSON() ([]byte,error) {
    return wrapJSON(`term-query`,fakeTermQuery(q))
}

func wrapJSON(name string,item interface{}) ([]byte,error) {
    var buffer bytes.Buffer
    b,err := json.Marshal(item)
    buffer.Write([]byte(`{"`))
    buffer.Write([]byte(name))
    buffer.Write([]byte(`":`))
    buffer.Write(b)
    buffer.Write([]byte(`}`))
    return buffer.Bytes(),err
}

我有很多已定义的结构,我需要这样做,所以我希望有一个更好的解决方案,不会让我用100行代码来添加一个围绕JSON对象的包装器.理想情况下,我希望能够在为XML编码器定义的XML元素名称处达到顶峰并使用它来包装JSON.

在我的情况下,我使用MarshalJSON函数,因为这些结构可以嵌套.如果有帮助我总是知道Query结构是根结构.

解决方法

也许我错过了一些东西,但这就是你要找的东西吗?

我开始时的想法和@Manawasp一样(使用map [string] interface {})但是我决定尝试从结构标记中获取名称,就像你问的那样……这就是我想出的结果(*注意:可能存在未处理的错误情况,这可能会使用其他解决方案很容易处理的事情过于复杂)

http://play.golang.org/p/qO6tDZjtXA

package main

import (
    "fmt"
    "reflect"
    "strings"
)
import (
    "encoding/json"
    "encoding/xml"
    "errors"
)

type Query struct {
    XMLName xml.Name `xml:"http://marklogic.com/appservices/search query" json:"-"`
    Field1  string
    Field2  int64
}

type TermQuery struct {
    XMLName xml.Name `xml:"http://marklogic.com/appservices/search term-query" json:"-"`
    Field3  string
    Field4  int64
}

func getXmlName(d interface{},label string) (string,bool) {
    switch reflect.TypeOf(d).Kind() {
    case reflect.Struct:
        v,_ := reflect.TypeOf(d).FieldByName(label)
        parts := strings.Split(v.Tag.Get("xml")," ")
        return parts[1],true
    }
    return "",false
}

func wrapJson(item interface{}) ([]byte,error) {
    if n,ok := getXmlName(item,"XMLName"); ok {
        b,err := json.Marshal(map[string]interface{}{n: item})
        if err != nil {
            return nil,err
        }
        return b,nil
    }
    return nil,errors.New("You failed")
}

func main() {
    // create a Query and encode it as {"query": {struct}}
    q := Query{Field1: "hello",Field2: 42}
    wrappedQ,err := wrapJson(q)
    if err != nil {
        fmt.Println(err)
        return
    }
    fmt.Println(string(wrappedQ))

    // create a TermQuery and encode it as {"term-query": {struct}}
    tq := TermQuery{Field3: "world",Field4: 99}
    wrappedTQ,err := wrapJson(tq)
    if err != nil {
        fmt.Println(err)
        return
    }
    fmt.Println(string(wrappedTQ))

}

OUTPUT

{"query":{"Field1":"hello","Field2":42}}
{"term-query":{"Field3":"world","Field4":99}}

编辑
好的,现在这是一个更新,我可以看到你的问题是什么.它可能是丑陋的,它可能不是防弹(错误处理等)……但是对于我的测试它似乎做你想要的.

http://play.golang.org/p/8MloLP3X4H

package main

import (
    "fmt"
    "reflect"
    "strings"
)
import (
    //"encoding/json"
    "encoding/json"
    "encoding/xml"
    "errors"
)

type Query struct {
    XMLName xml.Name `xml:"http://marklogic.com/appservices/search query" json:"-"`
    Field1  string
    Field2  int64
    Queries []interface{} `xml:",any" json:"queries"`
}

type TermQuery struct {
    XMLName xml.Name `xml:"http://marklogic.com/appservices/search term-query" json:"-"`
    Field3  string
    Field4  int64
}

func getXmlName(d interface{},true
    default:
        fmt.Println(reflect.TypeOf(d).Kind())
    }
    return "",false
}

func wrapJson(item interface{}) (map[string]interface{},"XMLName"); ok {

        if k := reflect.ValueOf(item).FieldByName("Queries"); k.IsValid() {
            for i := 0; i < k.Len(); i++ {
                b,err1 := wrapJson(k.Index(i).Interface())
                if err1 != nil {

                    continue
                }
                k.Index(i).Set(reflect.ValueOf(b))

            }

        }
        return map[string]interface{}{n: item},errors.New("You failed")
}

func asJson(i interface{}) []byte {
    b,err := json.Marshal(i)
    if err != nil {
        return []byte(`{"error": "too bad"}`)
    }
    return b
}

func main() {

    // create a TermQuery and encode it as {"term-query": {struct}}
    tq := TermQuery{Field3: "world",err := wrapJson(tq)
    if err != nil {
        fmt.Println(err)
        return
    }

    fmt.Println(string(asJson(wrappedTQ)))

    // create a Query and encode it as {"query": {struct}}
    q := Query{
        Field1: "hello",Field2: 42,Queries: []interface{}{
            TermQuery{Field3: "world",Field4: 99},TermQuery{Field3: "yay,it works!",Field4: 666},Query{
                Field1: "Hi",Field2: 21,Queries: []interface{}{
                    TermQuery{
                        Field3: "omg",Field4: 1,},}
    wrappedQ,err := wrapJson(q)
    if err != nil {
        fmt.Println(err)
        return
    }
    fmt.Println(string(asJson(wrappedQ)))

}

PRETTY-PRINTED OUTOUT

{
    "query": {
        "Field1": "hello","Field2": 42,"queries": [
            {
                "term-query": {
                    "Field3": "world","Field4": 99
                }
            },{
                "term-query": {
                    "Field3": "yay,"Field4": 666
                }
            },{
                "query": {
                    "Field1": "Hi","Field2": 21,"queries": [
                        {
                            "term-query": {
                                "Field3": "omg","Field4": 1
                            }
                        }
                    ]
                }
            }
        ]
    }
}

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读