Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

A bug of function httpx.ParseJsonBody while parse []interface{} #4259

Open
iporer opened this issue Jul 19, 2024 · 3 comments
Open

A bug of function httpx.ParseJsonBody while parse []interface{} #4259

iporer opened this issue Jul 19, 2024 · 3 comments
Assignees

Comments

@iporer
Copy link

iporer commented Jul 19, 2024

Describe the bug
A bug of function httpx.ParseJsonBody.
If I use A []interface{}json:"a" to parse, httpx.ParseJsonBody will panic with error reflect: Key of non-map type interface {}, but json.Unmarshal could parse successfully.

Otherwise, if I use A []Bjson:"a" to parse, httpx.ParseJsonBody could parse successfully.

To Reproduce
Steps to reproduce the behavior, if applicable:

  1. The code is

     	var req types.Req
     	if err := httpx.ParseJsonBody(r, &req); err != nil {
     		httpx.ErrorCtx(r.Context(), w, err)
     		return
     	}

body of requese:

 {"a":[{"b":"1"}]}
  1. The error is

    reflect: Key of non-map type interface {}
    

Expected behavior
Could parse json successfully while using interface{} array.

Screenshots
use json.Unmarshal could parse successfully.
image

Environments (please complete the following information):

  • OS: [Linux]
  • go-zero version [v1.6.0]
  • goctl version [1.6.3 linux/amd64]

More description
Add any other context about the problem here.

@iporer
Copy link
Author

iporer commented Jul 19, 2024

More code to test json.Unmarshal:

		var requestBody []byte
		requestBody, _ = io.ReadAll(r.Body)

		r.Body.Close()
		r.Body = io.NopCloser(bytes.NewBuffer(requestBody))

		logx.Infof("request body: %s", string(requestBody))

		var req types.Req
		json.Unmarshal(requestBody, &req)
		if err := httpx.ParseJsonBody(r, &req); err != nil {
			httpx.ErrorCtx(r.Context(), w, err)
			return
		}

@kevwan kevwan self-assigned this Jul 19, 2024
@streamsunshine
Copy link

I had the same problem

type Info struct {
    Name string `json:name`
}
type Req struct {
     Infos          []Info  `json:"infos"`
}
http body is  
{
  "infos": "[{}]"
}

then, httpx.PaseJsonBody will report reflect: Key of non-map Info
i find something wrong at https://github.com/zeromicro/go-zero/blob/master/core/mapping/unmarshaler.go#L614

case valueKind == reflect.String && typeKind == reflect.Slice:
		return u.fillSliceFromString(fieldType, value, mapValue, fullName)

i think it should return type mismatch error rather than continue parsing

@streamsunshine
Copy link

func (u *Unmarshaler) fillSliceFromString(fieldType reflect.Type, value reflect.Value,
mapValue any, fullName string) error {

switch v := mapValue.(type) {
case fmt.Stringer:
	if err := jsonx.UnmarshalFromString(v.String(), value.Addr().Interface()); err != nil {
		return err
	}
case string:
	if err := jsonx.UnmarshalFromString(v, value.Addr().Interface()); err != nil {
		return err
	}
default:
	return errUnsupportedType
}

return nil

}
https://github.com/zeromicro/go-zero/blob/master/core/mapping/unmarshaler.go#L222 seems a little complicated. The above code seems to work

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants