如何将输入作为 JSON 字符串,并根据条件将其转换为任意对象?

huangapple go评论83阅读模式
英文:

How to take input as json string and later convert it to any object based on condition

问题

这里我想将DefaultResponse作为字符串,但在映射到任何JSON结构之前,我想验证它是否是有效的JSON。

带有验证的完整代码可以在这里找到:
https://go.dev/play/p/knGNMj1QG3l

type AddEndpointRequest struct {
	Method            string `json:"method"`
	ContentType       int    `json:"contentType"`
	DefaultStatusCode int    `json:"defaultStatusCode"`
	DefaultResponse   string `json:"defaultResponse"`
}

我尝试了不同的选项,但它们都不起作用。

  1. 如果我传递这个: "defaultResponse":{"title":"Buy cheese and bread for breakfast."}
    会得到错误: json: 无法将对象解组为类型为string的Go结构字段AddEndpointRequest.defaultResponse

body := {"method":"GET","contentType":1,"defaultWaitTimeInMillis":100,"defaultStatusCode":200,"defaultResponse":"[{"p":"k"}]"}
错误: 对象键值对后的字符"p"无效

body := {"method":"GET","contentType":1,"defaultWaitTimeInMillis":100,"defaultStatusCode":200,"defaultResponse":"{"p":"k"}"}
./prog.go:21:117: 语法错误: 意外的{在语句结束处

  1. body := {"method":"GET","contentType":1,"defaultWaitTimeInMillis":100,"defaultStatusCode":200,"defaultResponse":"{/p/:/k/}"}

错误: ./prog.go:21:130: 语法错误: 意外的字面量"}"在语句结束处

还有其他很多错误。

英文:

Here I want to take DefaultResponse as String but later validate if it's a valid json before mapping to any json struct.

Complete code with validation can be found here :
https://go.dev/play/p/knGNMj1QG3l

type AddEndpointRequest struct {
	Method            string `json:"method"`
	ContentType       int    `json:"contentType"`
	DefaultStatusCode int    `json:"defaultStatusCode"`
	DefaultResponse   string `json:"defaultResponse"`
}

I tried different option but none of them are working

  1. if I pass this : “defaultResponse”:{“title”:“Buy cheese and bread for breakfast.”}
    Getting error : json: cannot unmarshal object into Go struct field AddEndpointRequest.defaultResponse of type string

2)
body := {"method":"GET","contentType":1,"defaultWaitTimeInMillis":100,"defaultStatusCode":200,"defaultResponse":"[{"p":"k"}]"}

Error : invalid character 'p' after object key:value pair

3)
body := {"method":"GET","contentType":1,"defaultWaitTimeInMillis":100,"defaultStatusCode":200,"defaultResponse":"{"p":"k"}"}
./prog.go:21:117: syntax error: unexpected { at end of statement

  1. body := {"method":"GET","contentType":1,"defaultWaitTimeInMillis":100,"defaultStatusCode":200,"defaultResponse":"{/"p/":/"k/"}"}
    Error : ./prog.go:21:130: syntax error: unexpected literal "}
    at end of statement

And many more

答案1

得分: 2

选项A:

将字段声明为字符串。在文档中,将字段值设置为有效的JSON字符串。请注意字符串中引号的转义。

type AddEndpointRequest struct {
    Method            string          `json:"method"`
    ContentType       int             `json:"contentType"`
    DefaultStatusCode int             `json:"defaultStatusCode"`
    DefaultResponse   string          `json:"defaultResponse"`
}

body := `{"method":"GET","contentType":1,"defaultWaitTimeInMillis":100,"defaultStatusCode":200,"defaultResponse":"{\"p\":\"k\"}"}`

将字段转换为[]byte以进行解组

```go
err := json.Unmarshal([]byte(request.DefaultResponse), &data)

https://go.dev/play/p/ailgQQ3eQBH

选项B:

将字段声明为json.RawMessage。在文档中,使用任何有效的JSON。

type AddEndpointRequest struct {
    Method            string          `json:"method"`
    ContentType       int             `json:"contentType"`
    DefaultStatusCode int             `json:"defaultStatusCode"`
    DefaultResponse   json.RawMessage `json:"defaultResponse"`
}

body := `{"method":"GET","contentType":1,"defaultWaitTimeInMillis":100,"defaultStatusCode":200,"defaultResponse":{"p":"k"}}`

调用`json.Unmarshal([]byte(body), &request)`将验证json.RawMessage字段如果json.Unmarshal的调用没有返回错误则应用程序可以确保AddEndpointRequest.DefaultResponse包含有效的JSON

像这样解组字段

```go
err := json.Unmarshal(request.DefaultResponse, &data)

https://go.dev/play/p/Xd_gWzJmvC_K

英文:

Option A:

Declare the field as a string. Use a valid JSON string as the field value in the document. Note the escaping of the quotes in the string.

type AddEndpointRequest struct {
	Method            string          `json:"method"`
	ContentType       int             `json:"contentType"`
	DefaultStatusCode int             `json:"defaultStatusCode"`
	DefaultResponse   string          `json:"defaultResponse"`
}
…
body := `{"method":"GET","contentType":1,"defaultWaitTimeInMillis":100,"defaultStatusCode":200,"defaultResponse":"{\"p\":\"k\"}"}`

Convert the field to a []byte to unmarshal:

err := json.Unmarshal([]byte(request.DefaultResponse), &data)

https://go.dev/play/p/ailgQQ3eQBH

Option B:

Declare the field as json.RawMessage. Use any valid JSON in the document.

type AddEndpointRequest struct {
	Method            string          `json:"method"`
	ContentType       int             `json:"contentType"`
	DefaultStatusCode int             `json:"defaultStatusCode"`
	DefaultResponse   json.RawMessage `json:"defaultResponse"`
}
…
body := `{"method":"GET","contentType":1,"defaultWaitTimeInMillis":100,"defaultStatusCode":200,"defaultResponse":{"p":"k"}}`

The call to json.Unmarshal([]byte(body), &request) validates the json.RawMessage field. If the call to json.Unmarshal does not return an error, then the application is assured that AddEndpointRequest.DefaultResponse contains valid JSON.

Unmarshal the field like this:

err := json.Unmarshal(request.DefaultResponse, &data)

https://go.dev/play/p/Xd_gWzJmvC_K

答案2

得分: 0

如果你想在defaultResponse中设置一个结构体,我认为可以按照以下方式进行操作。

package main

import (
	"encoding/json"
	"errors"
	"fmt"
)

type AddEndpointRequest struct {
	Method            string `json:"method"`
	ContentType       int    `json:"contentType"`
	DefaultStatusCode int    `json:"defaultStatusCode"`
	DefaultResponse   Response `json:"defaultResponse"`
}

type Response struct {
	Title string `json:"title"`
}

func main() {

	body := `{"method":"GET","contentType":1,"defaultWaitTimeInMillis":100,"defaultStatusCode":200,"defaultResponse":{"title":"Buy cheese and bread for breakfast."}}`
	fmt.Println("Hello GO")

	err := validateBody(body)
	if err != nil {
		fmt.Println("erro102")
		fmt.Println(err)

	}
}

func validateBody(body string) error {
	var data map[string]interface{}
	err := json.Unmarshal([]byte(body), &data)
	if err != nil {
		return errors.New("invalid json body provided for the request")
	}

	fmt.Println("data==>", data)

	fmt.Println("defaultResponse==>", data["defaultResponse"].(map[string]interface{})["title"])

	return nil
}

注意:我只翻译了代码部分,其他内容不做翻译。

英文:

If you want to set a struct in defaultResponse, I think doing it like this should work.

package main

import (
	"encoding/json"
	"errors"
	"fmt"
)

type AddEndpointRequest struct {
	Method            string `json:"method"`
	ContentType       int    `json:"contentType"`
	DefaultStatusCode int    `json:"defaultStatusCode"`
	DefaultResponse   string `json:"defaultResponse"`
}

func main() {

	body := `{"method":"GET","contentType":1,"defaultWaitTimeInMillis":100,"defaultStatusCode":200,"defaultResponse":{"title":"Buy cheese and bread for breakfast."}}`
	fmt.Println("Hello GO")

	err := validateBody(body)
	if err != nil {
		fmt.Println("erro102")
		fmt.Println(err)

	}
}

func validateBody(body string) error {
	var data map[string]interface{}
	err := json.Unmarshal([]byte(body), &data)
	if err != nil {
		return errors.New("invalid json body provided for the request")
	}

	fmt.Println("data===>", data)

	fmt.Println("defaultResponse===>", data["defaultResponse"].(map[string]interface{})["title"])

	return nil
}

huangapple
  • 本文由 发表于 2022年6月2日 03:54:13
  • 转载请务必保留本文链接:https://go.coder-hub.com/72467370.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定