आंशिक रूप से JSON गो में एक नक्शे में अनमर्ष है


98

मेरा वेबसैट सर्वर प्राप्त होगा और अनारक्षित 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)

EDIT: ध्यान रखें कि आपको अपने sendMsg स्ट्रक्चर में वैरिएबल को सही तरीके से अनमर्श करने के लिए एक्सपोर्ट करना होगा। तो आपकी संरचनात्मक परिभाषा यह होगी:

type sendMsg struct {
    User string
    Msg  string
}

उदाहरण: https://play.golang.org/p/OrIjvqIsi4-


6
उत्तम! मैंने याद किया है कि आप कैसे उपयोग कर सकते हैं RawMessage। बिल्कुल वही जो मुझे चाहिए था। के बारे में say, मैं वास्तव में अभी भी इसे चाहता हूं json.RawMessage, क्योंकि स्ट्रिंग अभी भी डीकोड नहीं किया गया है (रैपिंग "और एस्केप \n-चैकर्स, आदि), इसलिए मैं इसे भी अनमर्ष करूंगा।
एनिसस

1
मैंने अपना जवाब मैच के लिए तय किया कि आपने क्या किया। धन्यवाद
स्टीफन वेनबर्ग

3
इस प्रकार का नक्शा होना चाहिए [string] * json.RawMessage इसके बजाय क्योंकि jars.RawMessage पर Unmarshal / Marsal तरीके लागू नहीं होते हैं।
अल्बर्ट २०'१३ ४:

1
@albert, मेरे लिए काम करता है: play.golang.org/p/XYsozrJrSl । हालाँकि, आप सही हैं कि पॉइंटर का उपयोग करना बेहतर होगा। मेरे कोड का व्युत्क्रम सही से काम नहीं करता है: play.golang.org/p/46JOdjPpVI । एक सूचक का उपयोग करते हुए यह ठीक करता है: play.golang.org/p/ZGwhXkYUT3
स्टीफन वेनबर्ग

3
आपके द्वारा * json.RawMessage में अपडेट किए जाने के बाद, अब आपको कॉल में json.Unmarshal में उन्हें डीरेल करने की आवश्यकता है।
काइल नींबू

2

स्टीफन वेनबर्ग के जवाब के आगे, मैंने तब से iojson नामक एक आसान उपकरण को लागू किया है , जो किसी मौजूदा वस्तु को आसानी से और साथ ही साथ JSON स्ट्रिंग को मौजूदा ऑब्जेक्ट को एन्कोड करने के लिए डेटा को पॉप्युलेट करने में मदद करता है। अन्य बिचौलियों के साथ काम करने के लिए एक 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. जसन को संरचना में रखें।
  3. अब आप संरचना / ऑब्जेक्ट में सब कुछ आसानी से एक्सेस कर सकते हैं।

काम कोड पर नीचे देखें। इसे कॉपी और पेस्ट करें।

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 प्राप्त करें, एकल फ़ील्ड अपडेट करें और इसे सर्वर पर वापस पोस्ट करें।
आर्टेम बासकाकोव
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.