어떤 입력이 골랑의 json을 발생시키는지.오류를 반환할 보안요원?
문서에서:
JSON은 순환 데이터 구조를 나타낼 수 없으며 Marshal은 이러한 구조를 처리하지 않습니다.순환 구조를 Marshal에게 전달하면 무한 재귀가 발생합니다.
런타임 패닉을 일으키는 이 상황을 경험했습니다.
내가 궁금한 것은 json이 패닉에 빠지지 않는 상황을 보여주는 프로그램을 제공할 수 있는 사람이 있느냐는 것이다.Marshal이 nil 이외의 오류를 반환합니다.최선의 답변에는 사용된 입력이 포함됩니다.
조나단의 대답을 보완하기 위해서죠, json.Marshal 함수는 다음 두 가지 유형의 오류를 반환할 수 있습니다.UnsupportedTypeError또는UnsupportedValueError
조나단이 말한 것처럼 첫 번째 유형은 유효하지 않은 유형으로 분류하려고 하면 발생할 수 있습니다.
_, err := json.Marshal(make(chan int))
_, ok := err.(*json.UnsupportedTypeError) // ok == true
한편, Marshal 함수가 잘못된 값을 전달하여 오류를 반환하도록 할 수도 있습니다.
_, err := json.Marshal(math.Inf(1))
_, ok := err.(*json.UnsupportedValueError) // ok == true
업데이트: 이제 오류를 유도하기 위해 map[int]int 대신 채널을 사용합니다.
특정 구조, 예를 들어func또는chan연재 거부:
package main
import (
"encoding/json"
"fmt"
)
func main() {
value := make(chan int)
_, err := json.Marshal(value)
fmt.Println(err)
}
찾을 수 있는 소스 코드를 읽고 인코더가 존재하지 않으면 marshal 오류가 반환된다고 판단합니다.https://github.com/golang/go/blob/master/src/encoding/json/encode.go
func newTypeEncoder(t reflect.Type, allowAddr bool) encoderFunc {
// ignored
switch t.Kind() {
case reflect.Bool:
return boolEncoder
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
return intEncoder
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
return uintEncoder
case reflect.Float32:
return float32Encoder
case reflect.Float64:
return float64Encoder
case reflect.String:
return stringEncoder
case reflect.Interface:
return interfaceEncoder
case reflect.Struct:
return newStructEncoder(t)
case reflect.Map:
return newMapEncoder(t)
case reflect.Slice:
return newSliceEncoder(t)
case reflect.Array:
return newArrayEncoder(t)
case reflect.Ptr:
return newPtrEncoder(t)
default:
return unsupportedTypeEncoder
}
}
모든 종류의 열거형은 https://github.com/golang/go/blob/master/src/reflect/type.go에서 찾을 수 있습니다.
따라서 위의 함수에 포함되지 않은 종류가 분류할 수 없는 것은 어렵지 않습니다.
UnsafePointer,Complex64,Complex128,Chan,Func
예:
json.Marshal(unsafe.Pointer(nil)) // UnsafePointer
json.Marshal(complex64(1)) // Complex64
json.Marshal(complex128(1)) // Complex128
json.Marshal(make(chan struct{})) // Chan
json.Marshal(func() {}) // Func
얼마 전 골랑에서 순환 참조를 직렬화/비직렬화하는 문제를 해결하고 있었는데, 모든 링크가 이 질문으로 넘어갑니다.하지만 질문이 넓어서 조금 오해의 소지가 있습니다.
저와 같은 상황에 처해서 순환 참조에 대한 해결책을 찾을 수 없다면, 이제 제가 github에 게시한 새로운 라이브러리인 tahwil을 사용할 수 있습니다.제가 아는 바로는 현재 일반적인 방법으로 순환 데이터 구조의 직렬화/비직렬화를 지원하는 유일한 라이브러리입니다.
Readme는 라이브러리 사용 방법에 대한 정보를 제공하므로 여기서는 예시만 복제합니다.
인코딩:
package main
import (
"encoding/json"
"fmt"
"github.com/go-extras/tahwil"
)
type Person struct {
Name string
Parent *Person
Children []*Person
}
func main() {
parent := &Person{
Name: "Arthur",
Children: []*Person{
{
Name: "Ford",
},
{
Name: "Trillian",
},
},
}
parent.Children[0].Parent = parent
parent.Children[1].Parent = parent
v, err := tahwil.ToValue(parent)
if err != nil {
panic(err)
}
res, err := json.Marshal(v)
if err != nil {
panic(err)
}
fmt.Println(string(res))
}
디코딩:
package main
import (
"encoding/json"
"fmt"
"github.com/go-extras/tahwil"
)
type Person struct {
Name string `json:"name"`
Parent *Person `json:"parent"`
Children []*Person `json:"children"`
}
func prepareData() []byte {
parent := &Person{
Name: "Arthur",
Children: []*Person{
{
Name: "Ford",
},
{
Name: "Trillian",
},
},
}
parent.Children[0].Parent = parent
parent.Children[1].Parent = parent
v, err := tahwil.ToValue(parent)
if err != nil {
panic(err)
}
res, err := json.Marshal(v)
if err != nil {
panic(err)
}
return res
}
func main() {
data := &tahwil.Value{}
res := prepareData()
err := json.Unmarshal(res, data)
if err != nil {
panic(err)
}
person := &Person{}
err = tahwil.FromValue(data, person)
if err != nil {
panic(err)
}
fmt.Printf(`Name: %s
Children:
- %s
-- parent name: %s
- %s
-- parent name: %s
`, person.Name,
person.Children[0].Name,
person.Children[0].Parent.Name,
person.Children[1].Name,
person.Children[1].Parent.Name)
}
주요 아이디어는 원본 데이터를 다음과 같이 변환하는 것입니다.tahwil.Value{}즉, 기본적으로는refid모든 분야를 대상으로 합니다.언제든지tahwil는 순환 참조를 발견하면 실제 객체를 참조로 바꿉니다.그 후 그래프는 기술적으로 더 이상 순환적이지 않으므로 json으로 마샬링할 수 있습니다.
데이터 복원은 역연산을 의미합니다. 즉, 참조는 객체에 대한 포인터로 대체됩니다.
왜?tahwil이름에서 특이한 단어를 찾았는데 아랍어로 변환이라는 뜻의 단어(ت는 것)가 나왔어요.
언급URL : https://stackoverflow.com/questions/33903552/what-input-will-cause-golangs-json-marshal-to-return-an-error
'programing' 카테고리의 다른 글
| 리액트 훅 - 변수와 useState 사용 (0) | 2023.03.14 |
|---|---|
| Alert Json 개체 (0) | 2023.03.14 |
| WordPress "wp_register_style이 잘못 호출되었습니다?" (0) | 2023.03.14 |
| my.cnf에 대한 Mysqltuner 제안 및 변경 사항 (0) | 2023.03.14 |
| WordPress에서 모든 게시물을 표시하는 방법 (0) | 2023.03.14 |