convert string to json in golang and vice versa?

17,082

Solution 1

If I understand your problem correctly, you want to use json.RawMessage as Context.

RawMessage is a raw encoded JSON object. It implements Marshaler and Unmarshaler and can be used to delay JSON decoding or precompute a JSON encoding.

RawMessage is just []byte, so you can keep it in data store and then attach it for an outgoing messages as "precomputed JSON".

type Iot struct {
    Id      int             `json:"id"`
    Name    string          `json:"name"`
    Context json.RawMessage `json:"context"` // RawMessage here! (not a string)
}

func main() {
    in := []byte(`{"id":1,"name":"test","context":{"key1":"value1","key2":2}}`)

    var iot Iot
    err := json.Unmarshal(in, &iot)
    if err != nil {
        panic(err)
    }

    // Context is []byte, so you can keep it as string in DB
    fmt.Println("ctx:", string(iot.Context))

    // Marshal back to json (as original)
    out, _ := json.Marshal(&iot)
    fmt.Println(string(out))
}

https://play.golang.org/p/69n0B2PNRv

Solution 2

If you have no structured data and you really need to send a full JSON, then you can read it like this:

// an arbitrary json string
jsonString := "{\"foo\":{\"baz\": [1,2,3]}}"

var jsonMap map[string]interface{}
json.Unmarshal([]byte(jsonString ), &jsonMap)

fmt.Println(jsonMap)    
// prints: map[foo:map[baz:[1 2 3]]]

Of course, this has a big disadvantage, in that you don't know what is the content of each item, so you need to cast each of the children of the object to its proper type before using it.

// inner items are of type interface{}
foo := jsonMap["foo"]

// convert foo to the proper type
fooMap := foo.(map[string]interface{})

// now we can use it, but its children are still interface{}
fmt.Println(fooMap["baz"])

You could simplify this if the JSON you send can be more structured, but if you want to accept any kind of JSON string then you have to check everything and cast to the correct type before using the data.

You can find the code working in this playground.

Solution 3

I little also don't know what You want to do exacly, but in go I know two ways to convert some received data to json. This data should be as []byte type

first is allow to compiler choice interface and try parsed to JSON in this way:

[]byte(`{"monster":[{"basic":0,"fun":11,"count":262}],"m":"18"}`) 
bufferSingleMap   map[string]interface{}
json.Unmarshal(buffer , &bufferSingleMap)

socond if You know how exacly looks received data You can first define structure

type Datas struct{

    Monster []struct {
        Basic int     `json:"basic"`
        Fun int       `json:"fun"`
        Count int     `json:"count"`
    }                 `json:"Monster"`
    M int             `json:"m"`
}

Datas datas;
json.Unmarshal(buffer , &datas)

Imporant is name value. Should be writed with a capital letter (Fun, Count) This is a sign for Unmarshal that should be json. If You still don't can parsed to JSON show us Your received data, may be they have a bad syntax

Share:
17,082
MayK
Author by

MayK

I write code.

Updated on June 15, 2022

Comments

  • MayK
    MayK almost 2 years

    In my app, I receive a json from the client. This json can be anything since the user defines the keys and the values. In the backend I store it as string in the datastore.

    Now i'm trying to override the MarshalJson / UnmarshalJson functions so that what I send / receive from the client is not a string but a json.

    I can't figure out how to convert a string to json in go.

    my structure

    type ContextData string
    type Iot struct {
    Id              IotId       `json:"id,string" datastore:"-" goon:"id"`
    Name            string   `json:"name"`
    Context         ContextData  `json:"context" datastore:",noindex"` }
    

    example of received data

    { 'id' : '',
      'name' '',
      'context': {
               'key1': value1,
               'key2': value2 }}
    

    how i want to store this Context field in the datastore as a noindex string '{'key1':value1, 'key2':value2}' example of data i want to send

    { 'id' : '',
      'name' '',
      'context': {
               'key1': value1,
               'key2': value2 }}