dqdfpmmi022763 2015-11-12 03:22
浏览 152
已采纳

我可以修改json.RawMessage吗?

This is a follow up to JSON sometimes array sometimes object

In the original question, I asked how to deal with: "I am consuming a json API that might return a string for a variable or might return an array for a variable"

I have a solution but I was wondering, is there a way to modify json.RawMessage?

Rather then if/then looking at the RawMessage for a [ or { char to determine if the object is an array or an string, what if I always took a RawMessage variable string and turned it into an array?

This way, I don't have to code all of the accessors for BOTH strings AND arrays. I could simply deal with arrays.

So my question is: Is there a way to modify the json.RawMessage?

eg:

Turn this:

{ 
  "net": {
    "comment": {
        "line":
            {
                "$": "All abuse issues will only be responded to by the Abuse",
                "@number": "0"
            }
    }
}

Into This:

{ 
  "net": {
    "comment": {
        "line": [
            {
                "$": "All abuse issues will only be responded to by the Abuse",
                "@number": "0"
            }
        ]
    }
}

So, that way, when I unmarshal into my struct, there is only 1 type of comment.line, Just line[] vs line[] AND line.

Thanks in advance.

I am a golang neophyte and I'm just getting my head wrapped around the difficulties of unmarshaling into an strongly typed language.

  • 写回答

2条回答 默认 最新

  • douhu1990 2015-11-12 04:52
    关注

    Yes, you can edit json.RawMessage type as it is simply an alias for []byte.

    That said, you don't need to keep raw type, just make your own implementation of the array type and in your custom Unmarshal function, make scalars an array.

    Here's an example (on Play).

    All we do here is see if the bytes for MagicArray starts with '[', if so, just unmarshal as normal. Otherwise, Unmarshal and append to slice.

    you will have to implement custom array for each type you want to work like this, but that's still probably better than trying to safely manipulate the json binary to try coerce the scalars into arrays.

    Another side benefit to this approach is you can it with the streaming json decoder, as in json.NewDecoder(reader).Decode(&obj)

    package main
    
    import "encoding/json"
    import "log"
    
    type MagicArray []interface{}
    
    func (ma *MagicArray) UnmarshalJSON(b []byte) error {
        if b[0] == '[' {
            return json.Unmarshal(b, (*[]interface{})(ma))
        } else {
            var obj interface{}
            if err := json.Unmarshal(b, &obj); err != nil {
                return err
            }
            *ma = append(*ma, obj)
        }
        return nil
    }
    func main() {
        myStruct := struct {
            A MagicArray
            B MagicArray
        }{}
    
        err := json.Unmarshal(jsonToDecode, &myStruct)
        if err != nil {
            log.Println("Fail:", err)
        } else {
            log.Println(myStruct)
        }
    }
    
    var jsonToDecode = []byte(`
        { 
        "A": "I am not an array", 
        "B":["I am an array"]
        }
    `)
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥15 Stata 面板数据模型选择
  • ¥20 idea运行测试代码报错问题
  • ¥15 网络监控:网络故障告警通知
  • ¥15 django项目运行报编码错误
  • ¥15 请问这个是什么意思?
  • ¥15 STM32驱动继电器
  • ¥15 Windows server update services
  • ¥15 关于#c语言#的问题:我现在在做一个墨水屏设计,2.9英寸的小屏怎么换4.2英寸大屏
  • ¥15 模糊pid与pid仿真结果几乎一样
  • ¥15 java的GUI的运用