Marshal of json.RawMessage

12,211

Solution 1

the methods on json.RawMessage all take a pointer receiver, which is why you're not able to utilize any of them; you don't have a pointer.

This "works" in the sense that it executes, but this is likely not the strategy that you want: http://play.golang.org/p/jYvh8nHata

basically you need this:

type Data struct {
    Name string
    Id   int
    Json *json.RawMessage
}

and then propagate that change through the rest of your program. What... what are you actually trying to do?

Solution 2

jorellis answer is correct for versions of Go before 1.8.

Go 1.8 and newer will correctly handle marshalling of both a pointer and non-pointer json.RawMessage.

Fixing commit: https://github.com/golang/go/commit/1625da24106b610f89ff7a67a11581df95f8e234

Share:
12,211
bsr
Author by

bsr

Updated on October 02, 2022

Comments

  • bsr
    bsr over 1 year

    Please find the code here http://play.golang.org/p/zdQ14ItNBZ

    I am keeping JSON data as RawMessage, but cannot decode it out. I need the containing struct to be Marshalled and Unmarshalled, but I would expect still be able to get the JSON field.

    code:

    package main
    
    import (
        "encoding/json"
        "fmt"
    )
    
    type Data struct {
        Name string
        Id   int
        Json json.RawMessage
    }
    type Data2 struct {
        Name string
        Id   int
    }
    
    
    func main() {
    
        tmp := Data2{"World", 2}
    
        b, err := json.Marshal(tmp)
        if err != nil {
            fmt.Println("Error %s", err.Error())
        }
        fmt.Println("b %s", string(b))
    
        test := Data{"Hello", 1, b}
        b2, err := json.Marshal(test)
        if err != nil {
            fmt.Println("Error %s", err.Error())
        }
    
        fmt.Println("b2 %s", string(b2))
    
        var d Data
        err = json.Unmarshal(b2, &d)
        if err != nil {
            fmt.Println("Error %s", err.Error())
        }
        fmt.Println("d.Json %s", string(d.Json))
    
        var tmp2 Data2
        err = json.Unmarshal(d.Json, &tmp2)
        if err != nil {
            fmt.Println("Error %s", err.Error())
        }
        fmt.Println("Data2 %+v", tmp2)
    
    }
    

    out:

    b %s {"Name":"World","Id":2}
    b2 %s {"Name":"Hello","Id":1,"Json":"eyJOYW1lIjoiV29ybGQiLCJJZCI6Mn0="}
    d.Json %s "eyJOYW1lIjoiV29ybGQiLCJJZCI6Mn0="
    Error %s json: cannot unmarshal string into Go value of type main.Data2
    Data2 %+v { 0}
    
  • bsr
    bsr over 10 years
    Thanks a lot. I knew about pointer receiver, and tried locally. might have made a mistake. I use this store some cached values, which just needed as an http json response. thanks again for the help.
  • codefreak
    codefreak about 8 years
    is there any equivalent of json.RawMessage in encoding/xml package?
  • Sam Whited
    Sam Whited almost 7 years
    @codefreak a bit late, but the encoding/xml package lets you EncodeToken directly, or use an ",innerxml" tag to unmarshal "raw" xml bytes.