POST请求嵌套JSON格式错误排查及Go语言实现问题
Let's break down why you're getting that "badly-formed JSON" error and fix both of your implementation approaches:
Root Cause of the Error
The API's error points to position 51 in your request body, which corresponds to the unquoted, unresolved variable names (like source) in your first approach, and missing/incorrectly labeled fields in your second approach. Both issues produce invalid JSON that the API can't parse.
Fix 1: Direct JSON String Concatenation
Your first approach fails because you're embedding raw variable names (e.g., source, destn) into the JSON string instead of replacing them with actual values. This creates invalid JSON syntax (unquoted identifiers where string/number values should be).
Corrected Code:
import ( "fmt" "net/http" "bytes" "log" "io/ioutil" "crypto/tls" ) func main() { apiUrl := "http://example.com" tr := &http.Transport{ TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, } // Use fmt.Sprintf to inject variable values into the JSON string // Note: Wrap string values in quotes, leave numeric values unquoted jsonStr := []byte(fmt.Sprintf(`{ "client_interface": { "source_address": "%s", "destination_address": %d, "message": "%s", "business_event_url": "%s" }, "server_interface": { "message_id": %d } }`, source, destn, encrypted_msg, settings.Message_CallbackURL, msg_id)) req, err := http.NewRequest("POST", apiUrl, bytes.NewBuffer(jsonStr)) if err != nil { log.Println("Error creating request:", err) return } req.Header.Set("Content-Type", "application/json") req.Header.Set("requestid", fmt.Sprintf("%d", msg_id)) req.Header.Set("Authorization", "Bearer "+conn_token) client := &http.Client{Transport: tr} resp, err := client.Do(req) if err != nil { log.Println("Error sending request:", err) return } defer resp.Body.Close() body, _ := ioutil.ReadAll(resp.Body) fmt.Println("Response:", string(body)) }
Important Note: This approach is fragile if your variables contain special characters (like quotes or backslashes). For production code, use the struct serialization method below instead.
Fix 2: Struct Serialization (Recommended)
Your second approach has two critical issues:
- Unexported Fields: Go's
json.Marshalignores fields with lowercase names (they're not exported). - Incorrect JSON Tags: Your tags (e.g.,
json:"string") don't match the actual keys required by the API (they should bejson:"source_address", etc.).
Corrected Code:
package main import ( "fmt" "net/http" "io/ioutil" "bytes" "encoding/json" ) // Define structs with exported fields (uppercase first letter) and correct JSON tags type ClientInterface struct { SourceAddress string `json:"source_address"` DestinationAddress uint64 `json:"destination_address"` Message string `json:"message"` BusinessEventURL string `json:"business_event_url"` } type ServerInterface struct { MessageID uint64 `json:"message_id"` } type RequestData struct { ClientInterface ClientInterface `json:"client_interface"` ServerInterface ServerInterface `json:"server_interface"` } func main() { url := "https://example.com" fmt.Println("URL:>", url) // Populate structs with actual values clientIf := ClientInterface{ SourceAddress: "1", DestinationAddress: 1111111111, Message: "khsjhdjks", BusinessEventURL: "http://callbackurl-hdfc", } serverIf := ServerInterface{ MessageID: 8210993557215399651, } requestBody := RequestData{ ClientInterface: clientIf, ServerInterface: serverIf, } // Serialize struct to JSON (automatically handles valid syntax) jsonBytes, err := json.Marshal(requestBody) if err != nil { fmt.Println("JSON serialization error:", err) return } fmt.Println("Serialized JSON:", string(jsonBytes)) // Debug: verify output req, err := http.NewRequest("POST", url, bytes.NewReader(jsonBytes)) if err != nil { fmt.Println("Request creation error:", err) return } req.Header.Set("Content-Type", "application/json") req.Header.Set("requestid", "8210993557215399651") req.Header.Set("Authorization", "Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6IkJCOENlRlZxeWFHckdOdWVoSklpTDRkZmp6dyIsImtpZCI6IkJCOENlRlZxeWFHckdOdWVoSklpTDRkZmp6dyJ9.eyJhdWQiOiJhcGk6Ly90cC1kZXYtdGFubGEtYXBpIiwiaXNzIjoiaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvY2JhYThhYmItZTcwZi00YmI4LWIwNDQtZmZiZjAwNzk0NzkwLyIsImlhdCI6MTU3NTg5MTI3NCwibmJmIjoxNTc1ODkxMjc0LCJleHAiOjE1NzU4OTUxNzQsImFjciI6IjEiLCJhaW8iOiI0MlZnWU9EY3JjenlhZXIxdkRMRDVlNHVtWUxha1UrRUplOVYrZGVlRFgrOTNUMytNRGNBIiwiYW1yIjpbInB3ZCJdLCJhcHBpZCI6IjFmMjI1N2ZlLWIzYjktNGQ2Ny05M2YyLWRjNjM2N2Q2MGM4MCIsImFwcGlkYWNyIjoiMCIsImlwYWRkciI6IjE0LjE0My4xODcuMjUwIiwibmFtZSI6ImhkZmMuMTEiLCJvaWQiOiIzOGQxMGFlNS01OGYyLTQ0NjUtYTFkOC04YTc0NDAzYjc5MmEiLCJzY3AiOiJ1c2VyX2ltcGVyc29uYXRpb24iLCJzdWIiOiIzNDdUd0ZwYUw5MDhmOXlNRWlGOWNHMU84THFQYmJxZk45VzhyQWVEX1prIiwidGlkIjoiY2JhYThhYmItZTcwZi00YmI4LWIwNDQtZmZiZjAwNzk0NzkwIiwidW5pcXVlX25hbWUiOiJoZGZjLjExQFRhbmxhUHJvZHVjdC5vbm1pY3Jvc29mdC5jb20iLCJ1cG4iOiJoZGZjLjExQFRhbmxhUHJvZHVjdC5vbm1pY3Jvc29mdC5jb20iLCJ1dGkiOiJuS05TTXRsT3VFeXMtQjRIOGJ3TEFRIiwidmVyIjoiMS4wIn0.F5H9WCOktau3JaqNyWM91A5jFpJ9eJE99fBWvqDq9kOfCk3OCJnHFKXtIaIA7MoqbxWpNZt1yWpVKuw8gd2Lg_9nfUvvXts2DJHVQN0EqQmFUyWTzhdLW8ZVi6E9RtXK2aEWrI2TVceL5C2wbYOQYfvV4LzjTuNbs6k_20cQ0nD6oO1Id16VVFQWy9yKvpDzsTrvlQdFBZeohIfyL9XWKa8DOk0gxe4bjC7OFmuMsF3FZE5XPaQPHOJ3ejlZJiApml2TlRHnvLpkn1biE3NTAu9aO2lE262lyLg8ZaU0sbPuQaS8P797a-outxLvKEMh07895mA9g6vMxEdRV9X2eA") client := &http.Client{} resp, err := client.Do(req) if err != nil { panic(err) } defer resp.Body.Close() fmt.Println("response Status:", resp.Status) fmt.Println("response Headers:", resp.Header) body, _ := ioutil.ReadAll(resp.Body) fmt.Println("response Body:", string(body)) }
Key Fixes:
- Uppercased struct field names to export them for
json.Marshal - Updated JSON tags to exactly match the keys expected by the API
- Added error checking for JSON serialization to catch issues early
Additional Debug Tips
- Always print the serialized JSON string before sending it to verify it matches the API's requirements
- Use tools like JSONLint to validate your JSON syntax if you're unsure
内容的提问来源于stack exchange,提问作者Vani Polnedi

