Go에서 부분적으로 JSON을 맵으로 비 정렬 화


98

내 웹 소켓 서버는 JSON 데이터를 수신하고 마샬링 해제합니다. 이 데이터는 항상 키 / 값 쌍이있는 개체에 래핑됩니다. 키 문자열은 값 식별자 역할을하여 Go 서버에 어떤 종류의 값인지 알려줍니다. 어떤 유형의 값을 알면 올바른 유형의 구조체로 값을 정렬 해제하는 JSON으로 진행할 수 있습니다.

각 json- 객체에는 여러 키 / 값 쌍이 포함될 수 있습니다.

예제 JSON :

{
    "sendMsg":{"user":"ANisus","msg":"Trying to send a message"},
    "say":"Hello"
}

"encoding/json"작업을 수행하기 위해 패키지를 사용하는 쉬운 방법 이 있습니까?

package main

import (
    "encoding/json"
    "fmt"
)

// the struct for the value of a "sendMsg"-command
type sendMsg struct {
    user string
    msg  string
}
// The type for the value of a "say"-command
type say string

func main(){
    data := []byte(`{"sendMsg":{"user":"ANisus","msg":"Trying to send a message"},"say":"Hello"}`)

    // This won't work because json.MapObject([]byte) doesn't exist
    objmap, err := json.MapObject(data)

    // This is what I wish the objmap to contain
    //var objmap = map[string][]byte {
    //  "sendMsg": []byte(`{"user":"ANisus","msg":"Trying to send a message"}`),
    //  "say": []byte(`"hello"`),
    //}
    fmt.Printf("%v", objmap)
}

어떤 종류의 제안 / 도움을 주셔서 감사합니다!

답변:


195

이것은 map[string]json.RawMessage.

var objmap map[string]json.RawMessage
err := json.Unmarshal(data, &objmap)

추가로 구문 분석하려면 sendMsg다음과 같이 할 수 있습니다.

var s sendMsg
err = json.Unmarshal(objmap["sendMsg"], &s)

의 경우 say동일한 작업을 수행하고 문자열로 역 정렬화할 수 있습니다.

var str string
err = json.Unmarshal(objmap["say"], &str)

편집 : 올바른 비 정렬 화를 위해 sendMsg 구조체의 변수를 내 보내야합니다. 따라서 구조체 정의는 다음과 같습니다.

type sendMsg struct {
    User string
    Msg  string
}

예 : https://play.golang.org/p/OrIjvqIsi4-


6
완전한! 을 (를) 사용하는 방법을 놓쳤습니다 RawMessage. 정확히 내가 필요한 것. 에 관해서 는 문자열이 여전히 디코딩되지 않았기 때문에 (래핑 및 이스케이프 문자 등) say실제로 여전히 . json.RawMessage"\n
ANisus

1
나는 당신이 한 일과 일치하도록 내 대답을 수정했습니다. 감사합니다
Stephen Weinberg

3
Unmarshal / Marshal 메서드는 json.RawMessage에서 구현되지 않으므로 형식은 대신 map [string] * json.RawMessage 여야합니다.
albert

1
@albert, 나를 위해 일합니다 : play.golang.org/p/XYsozrJrSl . 그러나 포인터를 사용하는 것이 더 낫다는 것은 맞습니다. 내 코드의 역이 올바르게 작동하지 않습니다 : play.golang.org/p/46JOdjPpVI . 포인터를 사용하면 문제가 해결됩니다 : play.golang.org/p/ZGwhXkYUT3 .
Stephen Weinberg 2013 년

3
* json.RawMessage로 업데이트 한 후에는 이제 json.Unmarshal에 대한 호출에서이를 역 참조해야합니다.
Kyle Lemons

2

Stephen Weinberg의 대답에 더해 , 나는 기존 객체에 데이터를 쉽게 채우고 기존 객체를 JSON 문자열로 인코딩하는 데 도움이되는 iojson 이라는 편리한 도구를 구현했습니다 . 다른 미들웨어와 함께 작동하도록 iojson 미들웨어도 제공됩니다. 더 많은 예제는 https://github.com/junhsieh/iojson 에서 찾을 수 있습니다.

예:

func main() {
    jsonStr := `{"Status":true,"ErrArr":[],"ObjArr":[{"Name":"My luxury car","ItemArr":[{"Name":"Bag"},{"Name":"Pen"}]}],"ObjMap":{}}`

    car := NewCar()

    i := iojson.NewIOJSON()

    if err := i.Decode(strings.NewReader(jsonStr)); err != nil {
        fmt.Printf("err: %s\n", err.Error())
    }

    // populating data to a live car object.
    if v, err := i.GetObjFromArr(0, car); err != nil {
        fmt.Printf("err: %s\n", err.Error())
    } else {
        fmt.Printf("car (original): %s\n", car.GetName())
        fmt.Printf("car (returned): %s\n", v.(*Car).GetName())

        for k, item := range car.ItemArr {
            fmt.Printf("ItemArr[%d] of car (original): %s\n", k, item.GetName())
        }

        for k, item := range v.(*Car).ItemArr {
            fmt.Printf("ItemArr[%d] of car (returned): %s\n", k, item.GetName())
        }
    }
}

샘플 출력 :

car (original): My luxury car
car (returned): My luxury car
ItemArr[0] of car (original): Bag
ItemArr[1] of car (original): Pen
ItemArr[0] of car (returned): Bag
ItemArr[1] of car (returned): Pen

1

비슷한 일을하는 우아한 방법이 있습니다. 하지만 왜 부분적으로 JSON을 비 정렬 화 하는가? 말이 안 돼.

  1. 채팅에 대한 구조를 만듭니다.
  2. json을 구조체로 디코딩합니다.
  3. 이제 Struct / Object의 모든 항목에 쉽게 액세스 할 수 있습니다.

작동 코드를 아래에서보십시오. 복사하여 붙여 넣으십시오.

import (
   "bytes"
   "encoding/json" // Encoding and Decoding Package
   "fmt"
 )

var messeging = `{
"say":"Hello",
"sendMsg":{
    "user":"ANisus",
    "msg":"Trying to send a message"
   }
}`

type SendMsg struct {
   User string `json:"user"`
   Msg  string `json:"msg"`
}

 type Chat struct {
   Say     string   `json:"say"`
   SendMsg *SendMsg `json:"sendMsg"`
}

func main() {
  /** Clean way to solve Json Decoding in Go */
  /** Excellent solution */

   var chat Chat
   r := bytes.NewReader([]byte(messeging))
   chatErr := json.NewDecoder(r).Decode(&chat)
   errHandler(chatErr)
   fmt.Println(chat.Say)
   fmt.Println(chat.SendMsg.User)
   fmt.Println(chat.SendMsg.Msg)

}

 func errHandler(err error) {
   if err != nil {
     fmt.Println(err)
     return
   }
 }

이동 놀이터


1
임시 객체로 수백 개의 중첩 된 필드 구조로 작업 할 때 부분 비 정렬 화가 필요합니다. 예를 들어 서버에서 json을 가져 와서 단일 필드를 업데이트 한 다음 서버에 다시 게시합니다.
Artem Baskakov
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.