ohler55 / ojg

Optimized JSON for Go
MIT License
857 stars 49 forks source link

Result Value Type #82

Closed zgsdr closed 2 years ago

zgsdr commented 2 years ago

Hello!

I am very interested in ojg repo, and want import it as an util into my repo. But I find that result type is always []interface{} even if the result should be a single value(like int/float/string..), I want to know why it is designed like this. And because I don't have enough time to read the source code, I want to know if it is safe for me to parse the result as follows: (1) Always treat the result as []interface{} (2) if I need single value, for example: string, try to parse the first element of the result to string. (3) if I need slice value, try to parse the whole result([]interface{}) to a typed slice(for example: []int64), if that failed, try to parse the first element of the result to the typed slice.

Anyway, thanks for your help!

ohler55 commented 2 years ago

OjG has many functions. Can you tell me what function you are referring to?

zgsdr commented 2 years ago

Sorry, my fault.

here is my code:

obj ,_ := oj.ParseString(jsonString)
x, _ := jp.ParseString(jsonPath)
val := x.Get(obj)
ohler55 commented 2 years ago

So you are referring to the val := x.Get(obj) call I assume. Using a JSONPath to retrieve values can match more than one value to the result must be some kind of slice. Since the retrieved values can be of any type, the interface{} type must be used to cover all those cases. So a slice an "any" is []interface{}. To retrieve a single value you can use x.First(obj) which returns the first match as an interface{}. Returned value can aways be asserted to be the actual type so for example if the return from x.First(obj) is actually a string and that is expected then you could do something like str, ok := x.First(obj).(string). In that case, if ok is true then str will be the string value. You could also use the OjG alt.String() function if that suits your needs better.

To answer your questions directly: 1) The result of Get() is always a []interface{} as declared. It a feature of go that declaring the return type always results in that return type. 2) For a single value use First() instead. If a string is expected then assert as described above or use alt.String(). 3) I wasn't sure what you were asking on this one. There really isn't anything to parse from the result. If you attempt to assert that a []interface{} is an []int64 that will fail at compile time. You can iterate over the result and assert that each element is an int64 though.

zgsdr commented 2 years ago

So you are referring to the val := x.Get(obj) call I assume. Using a JSONPath to retrieve values can match more than one value to the result must be some kind of slice. Since the retrieved values can be of any type, the interface{} type must be used to cover all those cases. So a slice an "any" is []interface{}. To retrieve a single value you can use x.First(obj) which returns the first match as an interface{}. Returned value can aways be asserted to be the actual type so for example if the return from x.First(obj) is actually a string and that is expected then you could do something like str, ok := x.First(obj).(string). In that case, if ok is true then str will be the string value. You could also use the OjG alt.String() function if that suits your needs better.

To answer your questions directly:

  1. The result of Get() is always a []interface{} as declared. It a feature of go that declaring the return type always results in that return type.
  2. For a single value use First() instead. If a string is expected then assert as described above or use alt.String().
  3. I wasn't sure what you were asking on this one. There really isn't anything to parse from the result. If you attempt to assert that a []interface{} is an []int64 that will fail at compile time. You can iterate over the result and assert that each element is an int64 though.

Thank you for your clearly answer!!! It completely solves my problem!