গোপনে JSON পোস্ট অনুরোধ পরিচালনা করছে


250

সুতরাং আমার কাছে নিম্নলিখিতগুলি রয়েছে, যা অবিশ্বাস্যরূপে হ্যাকি বলে মনে হচ্ছে এবং আমি নিজেই ভাবছিলাম যে গো এর চেয়ে ভাল গ্রন্থাগারগুলি তৈরি করেছে তবে আমি জেএসওন ডেটার একটি পোষ্ট অনুরোধ পরিচালনা করে গো এর উদাহরণ খুঁজে পাচ্ছি না। এগুলি সবই পোষ্টের ফর্ম।

এখানে একটি উদাহরণ অনুরোধ: curl -X POST -d "{\"test\": \"that\"}" http://localhost:8082/test

এবং লগগুলি এমবেড করা সহ এখানে কোডটি রয়েছে:

package main

import (
    "encoding/json"
    "log"
    "net/http"
)

type test_struct struct {
    Test string
}

func test(rw http.ResponseWriter, req *http.Request) {
    req.ParseForm()
    log.Println(req.Form)
    //LOG: map[{"test": "that"}:[]]
    var t test_struct
    for key, _ := range req.Form {
        log.Println(key)
        //LOG: {"test": "that"}
        err := json.Unmarshal([]byte(key), &t)
        if err != nil {
            log.Println(err.Error())
        }
    }
    log.Println(t.Test)
    //LOG: that
}

func main() {
    http.HandleFunc("/test", test)
    log.Fatal(http.ListenAndServe(":8082", nil))
}

একটি ভাল উপায় আছে আছে, তাই না? আমি সর্বাধিক অনুশীলন কী হতে পারে তা সন্ধানে স্তব্ধ হয়ে পড়েছি।

(গো সার্চ ইঞ্জিনগুলিতে গোলং নামেও পরিচিত এবং অন্যরা এটির সন্ধান করতে পারে বলে এখানে উল্লেখ করেছেন))


3
আপনি যদি ব্যবহার করেন curl -X POST -H 'Content-Type: application/json' -d "{\"test\": \"that\"}"তবে req.Form["test"]ফিরে আসা উচিত"that"
Vinicius

@ ভিনিসিয়াস এর কোন প্রমাণ আছে কি?
ডায়রালিক

উত্তর:


388

json.Decoderপরিবর্তে ব্যবহার করুন json.Unmarshal

func test(rw http.ResponseWriter, req *http.Request) {
    decoder := json.NewDecoder(req.Body)
    var t test_struct
    err := decoder.Decode(&t)
    if err != nil {
        panic(err)
    }
    log.Println(t.Test)
}

79
আপনি দয়া করে কেন ব্যাখ্যা করতে পারেন?
রায়ান বিগ

86
শুরু করার জন্য, দেখে মনে হচ্ছে এটি নিজেকে কোনও বাফারে লোড করার প্রয়োজনের চেয়ে এটি কোনও স্ট্রিম পরিচালনা করতে পারে। (আমি আলাদা জো বিটিডাব্লু)
জো

7
এই ক্ষেত্রে সঠিক ত্রুটি পরিচালনা করা কেমন দেখায় আমি অবাক হই। আমি মনে করি না যে কোনও অবৈধ জসনকে আতঙ্কিত করা ভাল ধারণা।
কোডেপুশার

15
defer req.Body.Close()ডক্স থেকে আপনার প্রয়োজন হবে বলে আমি মনে করি না : "সার্ভার অনুরোধের বডিটি বন্ধ করে দেবে Ser সার্ভে এইচটিটিপি হ্যান্ডলারের প্রয়োজন নেই।" দস্তাবেজগুলি থেকে @ থিসিসনোটাবাসকে উত্তর দেওয়ার জন্য: "সার্ভারের অনুরোধের জন্য অনুরোধ বডিটি সর্বদা অ-শূন্য থাকে তবে কোনও শরীর উপস্থিত না হলে অবিলম্বে ইওএফ
ড্রু

22
আমি ব্যবহার না করার পরামর্শ দেব json.Decoder। এটি JSON অবজেক্টের স্ট্রিমের জন্য উদ্দেশ্যে করা হয়েছে, একটি একক অবজেক্ট নয়। এটি কোনও একক জেএসওএন বস্তুর পক্ষে কার্যকর নয় কারণ এটি পুরো বস্তুকে মেমোরিতে পড়ে। এটির একটি খারাপ দিক রয়েছে যে বস্তুর পরে আবর্জনা অন্তর্ভুক্ত করা হলে এটি অভিযোগ করবে না। কয়েকটি কারণের উপর নির্ভর করে, json.Decoderশরীর পুরোপুরি না পড়তে পারে এবং সংযোগটি পুনরায় ব্যবহারের জন্য অযোগ্য হবে be
কালে বি

85

আপনার কাছ থেকে পড়া দরকার req.BodyParseFormপদ্ধতি থেকে পড়া হয় req.Bodyএবং তারপর মান HTTP- র এনকোডেড বিন্যাসে পার্স। আপনি যা চান তা হ'ল দেহটি পড়ুন এবং এটিকে JSON ফর্ম্যাটে পার্স করুন।

আপনার কোড আপডেট হয়েছে।

package main

import (
    "encoding/json"
    "log"
    "net/http"
    "io/ioutil"
)

type test_struct struct {
    Test string
}

func test(rw http.ResponseWriter, req *http.Request) {
    body, err := ioutil.ReadAll(req.Body)
    if err != nil {
        panic(err)
    }
    log.Println(string(body))
    var t test_struct
    err = json.Unmarshal(body, &t)
    if err != nil {
        panic(err)
    }
    log.Println(t.Test)
}

func main() {
    http.HandleFunc("/test", test)
    log.Fatal(http.ListenAndServe(":8082", nil))
}

ধন্যবাদ! আমি এখন কোথায় ভুল হচ্ছিলাম তা দেখতে পাচ্ছি। আপনি যদি কল করেন req.ParseForm(), যা আমি এই সমস্যাটি সমাধান করার চেষ্টা করার আগে যা করেছি, আপনি চেষ্টা করার আগে এবং পড়ার আগে req.Body, এটি শরীর পরিষ্কার করে দেবে এবং unexpected end of JSON inputআপনি যাওয়ার সময় নিক্ষিপ্ত হবে বলে মনে হচ্ছে Unmarshal(কমপক্ষে
১.০.২-এ

1
@ ড্যানিয়েল: যখন আমি কার্ল করি - এক্স পোস্ট-ডি "{\" টেস্ট \ ": \" যে \ "}" লোকালহোস্ট: 8082 / পরীক্ষা , লগ.প্রিন্টলন (t.Test) খালি ফিরে আসে। কেন? বা সেই বিষয়ে যদি অন্য কোনও জেএসওন পোস্ট করে তবে তা খালি ফিরে আসে
সোমেশ

আপনার পোস্টের অনুরোধটি ভুল। পরীক্ষা! = পরীক্ষা প্রশংসা করি 5 বছর আগে ছিল: /
Rambatino

এটি একটি দুর্দান্ত সরল উদাহরণ!
15412

এটি ভাল পরামর্শ, তবে স্পষ্ট করে বলতে গেলে, ব্যবহারের বিষয়ে উল্লেখ করা উত্তরগুলিও json.NewDecoder(req.Body)সঠিক।
ধনী

59

এই সঠিক সমস্যাটি নিয়ে আমি নিজেকে পাগল করে চলেছি। আমার জেএসওএন মার্শালার এবং আনমারশালার আমার গো স্ট্রাক্টকে জনপ্রিয় করে তুলছিল না। তারপরে আমি https://eager.io/blog/go-and-json এ সমাধানটি পেয়েছি :

"গো-র সকল স্ট্রাক্টের মতো এটিও মনে রাখা গুরুত্বপূর্ণ যে কেবল বড় বড় অক্ষরযুক্ত ক্ষেত্রগুলি জেএসওন মার্শালারের মতো বাহ্যিক প্রোগ্রামগুলিতে দৃশ্যমান।"

এর পরে, আমার মার্শলার এবং আনমারশালার পুরোপুরি কাজ করেছিল!


লিঙ্ক থেকে কিছু স্নিপেট অন্তর্ভুক্ত করুন। যদি এটি অবনতি হয় তবে উদাহরণগুলি হারিয়ে যাবে।
030

47

কেন json.Decoderবেশি পছন্দ করা উচিত তার দুটি কারণ রয়েছে json.Unmarshal- যেগুলি ২০১৩ সালের সবচেয়ে জনপ্রিয় উত্তরে সম্বোধন করা হয়নি:

  1. ফেব্রুয়ারী 2018, go 1.10একটি নতুন পদ্ধতি জেসন.ডেকোডার.ডিসললোউনফ্যানডফিল্ডস () প্রবর্তন করে যা অযাচিত জেএসএন -ইনপুট সনাক্ত করার উদ্বেগকে সম্বোধন করে
  2. req.Bodyইতিমধ্যে একটি io.Reader। এর সম্পূর্ণ সামগ্রীগুলি পড়া এবং তারপরে json.Unmarshalযদি স্ট্রিমটি ছিল তবে রিসোর্সগুলির অপচয় করা সম্পাদনা করুন, অবৈধ জেএসওনের একটি 10 ​​এমবি ব্লক বলুন। অনুরোধের মূল অংশটি পার্স করা json.Decoderযেমন এটি প্রবাহিত হয় ততক্ষণে যদি অকার্যকর JSON এর মুখোমুখি হয় তবে পার্স ত্রুটিটিকে ট্রিগার করবে। রিয়েলটাইমে I / O স্ট্রিমগুলি প্রক্রিয়াকরণ করা পছন্দসই গো-ওয়ে

খারাপ ব্যবহারকারীর ইনপুট সনাক্তকরণ সম্পর্কে ব্যবহারকারীদের কয়েকটি মন্তব্যে সম্বোধন করা:

বাধ্যতামূলক ক্ষেত্র এবং অন্যান্য স্যানিটেশন চেক প্রয়োগ করতে, চেষ্টা করুন:

d := json.NewDecoder(req.Body)
d.DisallowUnknownFields() // catch unwanted fields

// anonymous struct type: handy for one-time use
t := struct {
    Test *string `json:"test"` // pointer so we can test for field absence
}{}

err := d.Decode(&t)
if err != nil {
    // bad JSON or unrecognized json field
    http.Error(rw, err.Error(), http.StatusBadRequest)
    return
}

if t.Test == nil {
    http.Error(rw, "missing field 'test' from JSON object", http.StatusBadRequest)
    return
}

// optional extra check
if d.More() {
    http.Error(rw, "extraneous data after JSON object", http.StatusBadRequest)
    return
}

// got the input we expected: no more, no less
log.Println(*t.Test)

খেলার মাঠ

সাধারণ আউটপুট:

$ curl -X POST -d "{}" http://localhost:8082/strict_test

expected json field 'test'

$ curl -X POST -d "{\"Test\":\"maybe?\",\"Unwanted\":\"1\"}" http://localhost:8082/strict_test

json: unknown field "Unwanted"

$ curl -X POST -d "{\"Test\":\"oops\"}g4rB4g3@#$%^&*" http://localhost:8082/strict_test

extraneous data after JSON

$ curl -X POST -d "{\"Test\":\"Works\"}" http://localhost:8082/strict_test 

log: 2019/03/07 16:03:13 Works

6
কিছু খারাপ বলে দেওয়ার পরিবর্তে মতামত ব্যাখ্যা করার জন্য আপনাকে ধন্যবাদ
Fjolnir Dvorak

আপনি জানেন কি এটি পরিচালনা করে না? আমি দেখেছি টেস্ট
দুটিবার জসনে

@ টুপটুপ 4 কে ডুপ্লিকেট ক্ষেত্রগুলি সম্পর্কে সতর্ক করতে একটি কাস্টম ডিকোডার লিখতে হবে - ডিকোডারে অদক্ষতা যুক্ত করে - এমন পরিস্থিতি হ্যান্ডেল করার জন্য যা কখনও ঘটে না। কোনও মানদণ্ডের JSON এনকোডার কখনও সদৃশ ক্ষেত্র তৈরি করতে পারে না।
colm.anseo

20

আমি ডক্স থেকে নিম্নলিখিত উদাহরণে সত্যিই সহায়ক (উৎস পাওয়া এখানে )।

package main

import (
    "encoding/json"
    "fmt"
    "io"
    "log"
    "strings"
)

func main() {
    const jsonStream = `
        {"Name": "Ed", "Text": "Knock knock."}
        {"Name": "Sam", "Text": "Who's there?"}
        {"Name": "Ed", "Text": "Go fmt."}
        {"Name": "Sam", "Text": "Go fmt who?"}
        {"Name": "Ed", "Text": "Go fmt yourself!"}
    `
    type Message struct {
        Name, Text string
    }
    dec := json.NewDecoder(strings.NewReader(jsonStream))
    for {
        var m Message
        if err := dec.Decode(&m); err == io.EOF {
            break
        } else if err != nil {
            log.Fatal(err)
        }
        fmt.Printf("%s: %s\n", m.Name, m.Text)
    }
}

এখানে কীটি হ'ল ওপি ডিকোড করতে চাইছিল to

type test_struct struct {
    Test string
}

... এই ক্ষেত্রে আমরা ড্রপটি ফেলে দেব const jsonStreamএবং Messageস্ট্রাক্টটি প্রতিস্থাপন করব test_struct:

func test(rw http.ResponseWriter, req *http.Request) {
    dec := json.NewDecoder(req.Body)
    for {
        var t test_struct
        if err := dec.Decode(&t); err == io.EOF {
            break
        } else if err != nil {
            log.Fatal(err)
        }
        log.Printf("%s\n", t.Test)
    }
}

আপডেট : আমি আরও যুক্ত করব যে এই পোস্টটি JSON এর সাথে প্রতিক্রিয়া জানাতেও দুর্দান্ত কিছু ডেটা সরবরাহ করে। লেখক ব্যাখ্যা করেছেন struct tags, যা সম্পর্কে আমি অবগত ছিলাম না।

যেহেতু জেএসএন সাধারণভাবে দেখতে লাগে না {"Test": "test", "SomeKey": "SomeVal"}, বরং {"test": "test", "somekey": "some value"}আপনি নিজের কাঠামোর পুনর্গঠন করতে পারেন:

type test_struct struct {
    Test string `json:"test"`
    SomeKey string `json:"some-key"`
}

... এবং এখন আপনার হ্যান্ডলার "সামারকি" (যা আপনি অভ্যন্তরীণভাবে ব্যবহার করবেন) এর বিপরীতে "কিছু-কী" ব্যবহার করে জেএসএনকে বিশ্লেষণ করবে।


আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.