package json_test

import (
	"bytes"
	"fmt"
	"testing"

	"github.com/goccy/go-json"
)

type coverSliceMarshalJSON struct {
	A int
}

func (coverSliceMarshalJSON) MarshalJSON() ([]byte, error) {
	return []byte(`"hello"`), nil
}

type coverSliceMarshalJSONMap map[string]any

func (c coverSliceMarshalJSONMap) MarshalJSON() ([]byte, error) {
	return json.Marshal(map[string]any(c))
}

type coverSliceMarshalJSONMapPtr map[string]any

func (c *coverSliceMarshalJSONMapPtr) MarshalJSON() ([]byte, error) {
	return json.Marshal(map[string]any(*c))
}

type coverSliceMarshalText struct {
	A int
}

func (coverSliceMarshalText) MarshalText() ([]byte, error) {
	return []byte(`"hello"`), nil
}

type recursiveSlice struct {
	A int
	B []*recursiveSlice
}

func TestCoverSlice(t *testing.T) {
	type structSlice struct {
		A []int `json:"a"`
	}
	type structSliceOmitEmpty struct {
		A []int `json:"a,omitempty"`
	}
	type structSliceString struct {
		A []int `json:"a,string"`
	}
	type structSlicePtr struct {
		A *[]int `json:"a"`
	}
	type structSlicePtrOmitEmpty struct {
		A *[]int `json:"a,omitempty"`
	}
	type structSlicePtrString struct {
		A *[]int `json:"a,string"`
	}

	type structSlicePtrContent struct {
		A []*int `json:"a"`
	}
	type structSliceOmitEmptyPtrContent struct {
		A []*int `json:"a,omitempty"`
	}
	type structSliceStringPtrContent struct {
		A []*int `json:"a,string"`
	}
	type structSlicePtrPtrContent struct {
		A *[]*int `json:"a"`
	}
	type structSlicePtrOmitEmptyPtrContent struct {
		A *[]*int `json:"a,omitempty"`
	}
	type structSlicePtrStringPtrContent struct {
		A *[]*int `json:"a,string"`
	}

	tests := []struct {
		name string
		data interface{}
	}{
		{
			name: "SliceInt",
			data: []int{1, 2, 3},
		},
		{
			name: "SliceInt8",
			data: []int8{1, 2, 3},
		},
		{
			name: "SliceInt16",
			data: []int16{1, 2, 3},
		},
		{
			name: "SliceInt32",
			data: []int32{1, 2, 3},
		},
		{
			name: "SliceInt64",
			data: []int64{1, 2, 3},
		},
		{
			name: "SliceUint",
			data: []uint{1, 2, 3},
		},
		{
			name: "SliceUint8",
			data: []uint8{1, 2, 3},
		},
		{
			name: "SliceUint16",
			data: []uint16{1, 2, 3},
		},
		{
			name: "SliceUint32",
			data: []uint32{1, 2, 3},
		},
		{
			name: "SliceUint64",
			data: []uint64{1, 2, 3},
		},
		{
			name: "SliceFloat32",
			data: []float32{1, 2, 3},
		},
		{
			name: "SliceFloat64",
			data: []float64{1, 2, 3},
		},
		{
			name: "SliceString",
			data: []string{"a", "b"},
		},
		{
			name: "SliceBool",
			data: []bool{false, true, false},
		},
		{
			name: "SliceBytes",
			data: [][]byte{[]byte("a"), []byte("b"), nil, []byte("c")},
		},
		{
			name: "SliceSlice",
			data: [][]int{[]int{1, 2, 3}, nil, []int{4, 5, 6}},
		},
		{
			name: "SliceArray",
			data: [][3]int{[3]int{1, 2, 3}, [3]int{4, 5, 6}},
		},
		{
			name: "SliceMap",
			data: []map[string]int{map[string]int{"a": 1}, nil, map[string]int{"b": 2}},
		},
		{
			name: "SliceStruct",
			data: []struct{ A int }{struct{ A int }{A: 1}, struct{ A int }{A: 2}},
		},
		{
			name: "SliceMarshalJSON",
			data: []coverSliceMarshalJSON{{A: 1}, {A: 2}},
		},
		{
			name: "SliceMarshalJSONMap",
			data: []coverSliceMarshalJSONMap{{"foo": "bar"}, {"some": 1}},
		},
		{
			name: "SliceMarshalJSONMap",
			data: []*coverSliceMarshalJSONMap{{"foo": "bar"}, {"some": 1}},
		},
		{
			name: "SliceMarshalJSONMap",
			data: []coverSliceMarshalJSONMapPtr{{"foo": "bar"}, {"some": 1}},
		},
		{
			name: "SliceMarshalJSONMap",
			data: []*coverSliceMarshalJSONMapPtr{{"foo": "bar"}, {"some": 1}},
		},
		{
			name: "SliceMarshalText",
			data: []coverSliceMarshalText{{A: 1}, {A: 2}},
		},
		{
			name: "SliceIntPtr",
			data: []*int{intptr(1), intptr(2), nil, intptr(3)},
		},
		{
			name: "SliceInt8Ptr",
			data: []*int8{int8ptr(1), int8ptr(2), nil, int8ptr(3)},
		},
		{
			name: "SliceInt16Ptr",
			data: []*int16{int16ptr(1), int16ptr(2), nil, int16ptr(3)},
		},
		{
			name: "SliceInt32Ptr",
			data: []*int32{int32ptr(1), int32ptr(2), nil, int32ptr(3)},
		},
		{
			name: "SliceInt64Ptr",
			data: []*int64{int64ptr(1), int64ptr(2), nil, int64ptr(3)},
		},
		{
			name: "SliceUintPtr",
			data: []*uint{uptr(1), uptr(2), nil, uptr(3)},
		},
		{
			name: "SliceUint8Ptr",
			data: []*uint8{uint8ptr(1), uint8ptr(2), nil, uint8ptr(3)},
		},
		{
			name: "SliceUint16Ptr",
			data: []*uint16{uint16ptr(1), uint16ptr(2), nil, uint16ptr(3)},
		},
		{
			name: "SliceUint32Ptr",
			data: []*uint32{uint32ptr(1), uint32ptr(2), nil, uint32ptr(3)},
		},
		{
			name: "SliceUint64Ptr",
			data: []*uint64{uint64ptr(1), uint64ptr(2), nil, uint64ptr(3)},
		},
		{
			name: "SliceFloat32Ptr",
			data: []*float32{float32ptr(1), float32ptr(2), nil, float32ptr(3)},
		},
		{
			name: "SliceFloat64Ptr",
			data: []*float64{float64ptr(1), float64ptr(2), nil, float64ptr(3)},
		},
		{
			name: "SliceStringPtr",
			data: []*string{stringptr("a"), nil, stringptr("b")},
		},
		{
			name: "SliceBoolPtr",
			data: []*bool{boolptr(false), boolptr(true), nil, boolptr(false)},
		},
		{
			name: "SliceBytesPtr",
			data: []*[]byte{bytesptr([]byte("a")), bytesptr([]byte("b")), nil, bytesptr([]byte("c"))},
		},
		{
			name: "SliceSlicePtr",
			data: []*[]int{sliceptr([]int{1, 2, 3}), nil, sliceptr([]int{4, 5, 6})},
		},
		{
			name: "SliceArrayPtr",
			data: []*[2]int{arrayptr([2]int{1, 2}), nil, arrayptr([2]int{4, 5})},
		},
		{
			name: "SliceMapPtr",
			data: []*map[string]int{mapptr(map[string]int{"a": 1}), nil, mapptr(map[string]int{"b": 2})},
		},
		{
			name: "SliceStructPtr",
			data: []*struct{ A int }{&struct{ A int }{A: 1}, &struct{ A int }{A: 2}},
		},
		{
			name: "RecursiveSlice",
			data: []*recursiveSlice{
				{
					A: 1, B: []*recursiveSlice{
						{
							A: 2, B: []*recursiveSlice{
								{
									A: 3,
								},
							},
						},
					},
				},
				{
					A: 4, B: []*recursiveSlice{
						{
							A: 5, B: []*recursiveSlice{
								{
									A: 6,
								},
							},
						},
					},
				},
			},
		},

		// HeadSliceZero
		{
			name: "HeadSliceZero",
			data: struct {
				A []int `json:"a"`
			}{},
		},
		{
			name: "HeadSliceZeroOmitEmpty",
			data: struct {
				A []int `json:"a,omitempty"`
			}{},
		},
		{
			name: "HeadSliceZeroString",
			data: struct {
				A []int `json:"a,string"`
			}{},
		},

		// HeadSlice
		{
			name: "HeadSlice",
			data: struct {
				A []int `json:"a"`
			}{A: []int{-1}},
		},
		{
			name: "HeadSliceOmitEmpty",
			data: struct {
				A []int `json:"a,omitempty"`
			}{A: []int{-1}},
		},
		{
			name: "HeadSliceString",
			data: struct {
				A []int `json:"a,string"`
			}{A: []int{-1}},
		},

		// HeadSlicePtr
		{
			name: "HeadSlicePtr",
			data: struct {
				A *[]int `json:"a"`
			}{A: sliceptr([]int{-1})},
		},
		{
			name: "HeadSlicePtrOmitEmpty",
			data: struct {
				A *[]int `json:"a,omitempty"`
			}{A: sliceptr([]int{-1})},
		},
		{
			name: "HeadSlicePtrString",
			data: struct {
				A *[]int `json:"a,string"`
			}{A: sliceptr([]int{-1})},
		},

		// HeadSlicePtrNil
		{
			name: "HeadSlicePtrNil",
			data: struct {
				A *[]int `json:"a"`
			}{A: nil},
		},
		{
			name: "HeadSlicePtrNilOmitEmpty",
			data: struct {
				A *[]int `json:"a,omitempty"`
			}{A: nil},
		},
		{
			name: "HeadSlicePtrNilString",
			data: struct {
				A *[]int `json:"a,string"`
			}{A: nil},
		},

		// PtrHeadSliceZero
		{
			name: "PtrHeadSliceZero",
			data: &struct {
				A []int `json:"a"`
			}{},
		},
		{
			name: "PtrHeadSliceZeroOmitEmpty",
			data: &struct {
				A []int `json:"a,omitempty"`
			}{},
		},
		{
			name: "PtrHeadSliceZeroString",
			data: &struct {
				A []int `json:"a,string"`
			}{},
		},

		// PtrHeadSlice
		{
			name: "PtrHeadSlice",
			data: &struct {
				A []int `json:"a"`
			}{A: []int{-1}},
		},
		{
			name: "PtrHeadSliceOmitEmpty",
			data: &struct {
				A []int `json:"a,omitempty"`
			}{A: []int{-1}},
		},
		{
			name: "PtrHeadSliceString",
			data: &struct {
				A []int `json:"a,string"`
			}{A: []int{-1}},
		},

		// PtrHeadSlicePtr
		{
			name: "PtrHeadSlicePtr",
			data: &struct {
				A *[]int `json:"a"`
			}{A: sliceptr([]int{-1})},
		},
		{
			name: "PtrHeadSlicePtrOmitEmpty",
			data: &struct {
				A *[]int `json:"a,omitempty"`
			}{A: sliceptr([]int{-1})},
		},
		{
			name: "PtrHeadSlicePtrString",
			data: &struct {
				A *[]int `json:"a,string"`
			}{A: sliceptr([]int{-1})},
		},

		// PtrHeadSlicePtrNil
		{
			name: "PtrHeadSlicePtrNil",
			data: &struct {
				A *[]int `json:"a"`
			}{A: nil},
		},
		{
			name: "PtrHeadSlicePtrNilOmitEmpty",
			data: &struct {
				A *[]int `json:"a,omitempty"`
			}{A: nil},
		},
		{
			name: "PtrHeadSlicePtrNilString",
			data: &struct {
				A *[]int `json:"a,string"`
			}{A: nil},
		},

		// PtrHeadSliceNil
		{
			name: "PtrHeadSliceNil",
			data: (*struct {
				A *[]int `json:"a"`
			})(nil),
		},
		{
			name: "PtrHeadSliceNilOmitEmpty",
			data: (*struct {
				A *[]int `json:"a,omitempty"`
			})(nil),
		},
		{
			name: "PtrHeadSliceNilString",
			data: (*struct {
				A *[]int `json:"a,string"`
			})(nil),
		},

		// HeadSliceZeroMultiFields
		{
			name: "HeadSliceZeroMultiFields",
			data: struct {
				A []int `json:"a"`
				B []int `json:"b"`
				C []int `json:"c"`
			}{},
		},
		{
			name: "HeadSliceZeroMultiFieldsOmitEmpty",
			data: struct {
				A []int `json:"a,omitempty"`
				B []int `json:"b,omitempty"`
				C []int `json:"c,omitempty"`
			}{},
		},
		{
			name: "HeadSliceZeroMultiFields",
			data: struct {
				A []int `json:"a,string"`
				B []int `json:"b,string"`
				C []int `json:"c,string"`
			}{},
		},

		// HeadSliceMultiFields
		{
			name: "HeadSliceMultiFields",
			data: struct {
				A []int `json:"a"`
				B []int `json:"b"`
				C []int `json:"c"`
			}{A: []int{-1}, B: []int{-2}, C: []int{-3}},
		},
		{
			name: "HeadSliceMultiFieldsOmitEmpty",
			data: struct {
				A []int `json:"a,omitempty"`
				B []int `json:"b,omitempty"`
				C []int `json:"c,omitempty"`
			}{A: []int{-1}, B: []int{-2}, C: []int{-3}},
		},
		{
			name: "HeadSliceMultiFieldsString",
			data: struct {
				A []int `json:"a,string"`
				B []int `json:"b,string"`
				C []int `json:"c,string"`
			}{A: []int{-1}, B: []int{-2}, C: []int{-3}},
		},

		// HeadSlicePtrMultiFields
		{
			name: "HeadSlicePtrMultiFields",
			data: struct {
				A *[]int `json:"a"`
				B *[]int `json:"b"`
				C *[]int `json:"c"`
			}{A: sliceptr([]int{-1}), B: sliceptr([]int{-2}), C: sliceptr([]int{-3})},
		},
		{
			name: "HeadSlicePtrMultiFieldsOmitEmpty",
			data: struct {
				A *[]int `json:"a,omitempty"`
				B *[]int `json:"b,omitempty"`
				C *[]int `json:"c,omitempty"`
			}{A: sliceptr([]int{-1}), B: sliceptr([]int{-2}), C: sliceptr([]int{-3})},
		},
		{
			name: "HeadSlicePtrMultiFieldsString",
			data: struct {
				A *[]int `json:"a,string"`
				B *[]int `json:"b,string"`
				C *[]int `json:"c,string"`
			}{A: sliceptr([]int{-1}), B: sliceptr([]int{-2}), C: sliceptr([]int{-3})},
		},

		// HeadSlicePtrNilMultiFields
		{
			name: "HeadSlicePtrNilMultiFields",
			data: struct {
				A *[]int `json:"a"`
				B *[]int `json:"b"`
				C *[]int `json:"c"`
			}{A: nil, B: nil, C: nil},
		},
		{
			name: "HeadSlicePtrNilMultiFieldsOmitEmpty",
			data: struct {
				A *[]int `json:"a,omitempty"`
				B *[]int `json:"b,omitempty"`
				C *[]int `json:"c,omitempty"`
			}{A: nil, B: nil, C: nil},
		},
		{
			name: "HeadSlicePtrNilMultiFieldsString",
			data: struct {
				A *[]int `json:"a,string"`
				B *[]int `json:"b,string"`
				C *[]int `json:"c,string"`
			}{A: nil, B: nil, C: nil},
		},

		// PtrHeadSliceZeroMultiFields
		{
			name: "PtrHeadSliceZeroMultiFields",
			data: &struct {
				A []int `json:"a"`
				B []int `json:"b"`
			}{},
		},
		{
			name: "PtrHeadSliceZeroMultiFieldsOmitEmpty",
			data: &struct {
				A []int `json:"a,omitempty"`
				B []int `json:"b,omitempty"`
			}{},
		},
		{
			name: "PtrHeadSliceZeroMultiFieldsString",
			data: &struct {
				A []int `json:"a,string"`
				B []int `json:"b,string"`
			}{},
		},

		// PtrHeadSliceMultiFields
		{
			name: "PtrHeadSliceMultiFields",
			data: &struct {
				A []int `json:"a"`
				B []int `json:"b"`
			}{A: []int{-1}, B: nil},
		},
		{
			name: "PtrHeadSliceMultiFieldsOmitEmpty",
			data: &struct {
				A []int `json:"a,omitempty"`
				B []int `json:"b,omitempty"`
			}{A: []int{-1}, B: nil},
		},
		{
			name: "PtrHeadSliceMultiFieldsString",
			data: &struct {
				A []int `json:"a,string"`
				B []int `json:"b,string"`
			}{A: []int{-1}, B: nil},
		},

		// PtrHeadSlicePtrMultiFields
		{
			name: "PtrHeadSlicePtrMultiFields",
			data: &struct {
				A *[]int `json:"a"`
				B *[]int `json:"b"`
			}{A: sliceptr([]int{-1}), B: sliceptr([]int{-2})},
		},
		{
			name: "PtrHeadSlicePtrMultiFieldsOmitEmpty",
			data: &struct {
				A *[]int `json:"a,omitempty"`
				B *[]int `json:"b,omitempty"`
			}{A: sliceptr([]int{-1}), B: sliceptr([]int{-2})},
		},
		{
			name: "PtrHeadSlicePtrMultiFieldsString",
			data: &struct {
				A *[]int `json:"a,string"`
				B *[]int `json:"b,string"`
			}{A: sliceptr([]int{-1}), B: sliceptr([]int{-2})},
		},

		// PtrHeadSlicePtrNilMultiFields
		{
			name: "PtrHeadSlicePtrNilMultiFields",
			data: &struct {
				A *[]int `json:"a"`
				B *[]int `json:"b"`
			}{A: nil, B: nil},
		},
		{
			name: "PtrHeadSlicePtrNilMultiFieldsOmitEmpty",
			data: &struct {
				A *[]int `json:"a,omitempty"`
				B *[]int `json:"b,omitempty"`
			}{A: nil, B: nil},
		},
		{
			name: "PtrHeadSlicePtrNilMultiFieldsString",
			data: &struct {
				A *[]int `json:"a,string"`
				B *[]int `json:"b,string"`
			}{A: nil, B: nil},
		},

		// PtrHeadSliceNilMultiFields
		{
			name: "PtrHeadSliceNilMultiFields",
			data: (*struct {
				A []int `json:"a"`
				B []int `json:"b"`
			})(nil),
		},
		{
			name: "PtrHeadSliceNilMultiFieldsOmitEmpty",
			data: (*struct {
				A []int `json:"a,omitempty"`
				B []int `json:"b,omitempty"`
			})(nil),
		},
		{
			name: "PtrHeadSliceNilMultiFieldsString",
			data: (*struct {
				A []int `json:"a,string"`
				B []int `json:"b,string"`
			})(nil),
		},

		// PtrHeadSliceNilMultiFields
		{
			name: "PtrHeadSliceNilMultiFields",
			data: (*struct {
				A *[]int `json:"a"`
				B *[]int `json:"b"`
			})(nil),
		},
		{
			name: "PtrHeadSliceNilMultiFieldsOmitEmpty",
			data: (*struct {
				A *[]int `json:"a,omitempty"`
				B *[]int `json:"b,omitempty"`
			})(nil),
		},
		{
			name: "PtrHeadSliceNilMultiFieldsString",
			data: (*struct {
				A *[]int `json:"a,string"`
				B *[]int `json:"b,string"`
			})(nil),
		},

		// HeadSliceZeroNotRoot
		{
			name: "HeadSliceZeroNotRoot",
			data: struct {
				A struct {
					A []int `json:"a"`
				}
			}{},
		},
		{
			name: "HeadSliceZeroNotRootOmitEmpty",
			data: struct {
				A struct {
					A []int `json:"a,omitempty"`
				}
			}{},
		},
		{
			name: "HeadSliceZeroNotRootString",
			data: struct {
				A struct {
					A []int `json:"a,string"`
				}
			}{},
		},

		// HeadSliceNotRoot
		{
			name: "HeadSliceNotRoot",
			data: struct {
				A struct {
					A []int `json:"a"`
				}
			}{A: struct {
				A []int `json:"a"`
			}{A: []int{-1}}},
		},
		{
			name: "HeadSliceNotRootOmitEmpty",
			data: struct {
				A struct {
					A []int `json:"a,omitempty"`
				}
			}{A: struct {
				A []int `json:"a,omitempty"`
			}{A: []int{-1}}},
		},
		{
			name: "HeadSliceNotRootString",
			data: struct {
				A struct {
					A []int `json:"a,string"`
				}
			}{A: struct {
				A []int `json:"a,string"`
			}{A: []int{-1}}},
		},

		// HeadSlicePtrNotRoot
		{
			name: "HeadSlicePtrNotRoot",
			data: struct {
				A struct {
					A *[]int `json:"a"`
				}
			}{A: struct {
				A *[]int `json:"a"`
			}{sliceptr([]int{-1})}},
		},
		{
			name: "HeadSlicePtrNotRootOmitEmpty",
			data: struct {
				A struct {
					A *[]int `json:"a,omitempty"`
				}
			}{A: struct {
				A *[]int `json:"a,omitempty"`
			}{sliceptr([]int{-1})}},
		},
		{
			name: "HeadSlicePtrNotRootString",
			data: struct {
				A struct {
					A *[]int `json:"a,string"`
				}
			}{A: struct {
				A *[]int `json:"a,string"`
			}{sliceptr([]int{-1})}},
		},

		// HeadSlicePtrNilNotRoot
		{
			name: "HeadSlicePtrNilNotRoot",
			data: struct {
				A struct {
					A *[]int `json:"a"`
				}
			}{},
		},
		{
			name: "HeadSlicePtrNilNotRootOmitEmpty",
			data: struct {
				A struct {
					A *[]int `json:"a,omitempty"`
				}
			}{},
		},
		{
			name: "HeadSlicePtrNilNotRootString",
			data: struct {
				A struct {
					A *[]int `json:"a,string"`
				}
			}{},
		},

		// PtrHeadSliceZeroNotRoot
		{
			name: "PtrHeadSliceZeroNotRoot",
			data: struct {
				A *struct {
					A []int `json:"a"`
				}
			}{A: new(struct {
				A []int `json:"a"`
			})},
		},
		{
			name: "PtrHeadSliceZeroNotRootOmitEmpty",
			data: struct {
				A *struct {
					A []int `json:"a,omitempty"`
				}
			}{A: new(struct {
				A []int `json:"a,omitempty"`
			})},
		},
		{
			name: "PtrHeadSliceZeroNotRootString",
			data: struct {
				A *struct {
					A []int `json:"a,string"`
				}
			}{A: new(struct {
				A []int `json:"a,string"`
			})},
		},

		// PtrHeadSliceNotRoot
		{
			name: "PtrHeadSliceNotRoot",
			data: struct {
				A *struct {
					A []int `json:"a"`
				}
			}{A: &(struct {
				A []int `json:"a"`
			}{A: []int{-1}})},
		},
		{
			name: "PtrHeadSliceNotRootOmitEmpty",
			data: struct {
				A *struct {
					A []int `json:"a,omitempty"`
				}
			}{A: &(struct {
				A []int `json:"a,omitempty"`
			}{A: []int{-1}})},
		},
		{
			name: "PtrHeadSliceNotRootString",
			data: struct {
				A *struct {
					A []int `json:"a,string"`
				}
			}{A: &(struct {
				A []int `json:"a,string"`
			}{A: []int{-1}})},
		},

		// PtrHeadSlicePtrNotRoot
		{
			name: "PtrHeadSlicePtrNotRoot",
			data: struct {
				A *struct {
					A *[]int `json:"a"`
				}
			}{A: &(struct {
				A *[]int `json:"a"`
			}{A: sliceptr([]int{-1})})},
		},
		{
			name: "PtrHeadSlicePtrNotRootOmitEmpty",
			data: struct {
				A *struct {
					A *[]int `json:"a,omitempty"`
				}
			}{A: &(struct {
				A *[]int `json:"a,omitempty"`
			}{A: sliceptr([]int{-1})})},
		},
		{
			name: "PtrHeadSlicePtrNotRootString",
			data: struct {
				A *struct {
					A *[]int `json:"a,string"`
				}
			}{A: &(struct {
				A *[]int `json:"a,string"`
			}{A: sliceptr([]int{-1})})},
		},

		// PtrHeadSlicePtrNilNotRoot
		{
			name: "PtrHeadSlicePtrNilNotRoot",
			data: struct {
				A *struct {
					A *[]int `json:"a"`
				}
			}{A: &(struct {
				A *[]int `json:"a"`
			}{A: nil})},
		},
		{
			name: "PtrHeadSlicePtrNilNotRootOmitEmpty",
			data: struct {
				A *struct {
					A *[]int `json:"a,omitempty"`
				}
			}{A: &(struct {
				A *[]int `json:"a,omitempty"`
			}{A: nil})},
		},
		{
			name: "PtrHeadSlicePtrNilNotRootString",
			data: struct {
				A *struct {
					A *[]int `json:"a,string"`
				}
			}{A: &(struct {
				A *[]int `json:"a,string"`
			}{A: nil})},
		},

		// PtrHeadSliceNilNotRoot
		{
			name: "PtrHeadSliceNilNotRoot",
			data: struct {
				A *struct {
					A *[]int `json:"a"`
				}
			}{A: nil},
		},
		{
			name: "PtrHeadSliceNilNotRootOmitEmpty",
			data: struct {
				A *struct {
					A *[]int `json:"a,omitempty"`
				} `json:",omitempty"`
			}{A: nil},
		},
		{
			name: "PtrHeadSliceNilNotRootString",
			data: struct {
				A *struct {
					A *[]int `json:"a,string"`
				} `json:",string"`
			}{A: nil},
		},

		// HeadSliceZeroMultiFieldsNotRoot
		{
			name: "HeadSliceZeroMultiFieldsNotRoot",
			data: struct {
				A struct {
					A []int `json:"a"`
				}
				B struct {
					B []int `json:"b"`
				}
			}{},
		},
		{
			name: "HeadSliceZeroMultiFieldsNotRootOmitEmpty",
			data: struct {
				A struct {
					A []int `json:"a,omitempty"`
				}
				B struct {
					B []int `json:"b,omitempty"`
				}
			}{},
		},
		{
			name: "HeadSliceZeroMultiFieldsNotRootString",
			data: struct {
				A struct {
					A []int `json:"a,string"`
				}
				B struct {
					B []int `json:"b,string"`
				}
			}{},
		},

		// HeadSliceMultiFieldsNotRoot
		{
			name: "HeadSliceMultiFieldsNotRoot",
			data: struct {
				A struct {
					A []int `json:"a"`
				}
				B struct {
					B []int `json:"b"`
				}
			}{A: struct {
				A []int `json:"a"`
			}{A: []int{-1}}, B: struct {
				B []int `json:"b"`
			}{B: []int{0}}},
		},
		{
			name: "HeadSliceMultiFieldsNotRootOmitEmpty",
			data: struct {
				A struct {
					A []int `json:"a,omitempty"`
				}
				B struct {
					B []int `json:"b,omitempty"`
				}
			}{A: struct {
				A []int `json:"a,omitempty"`
			}{A: []int{-1}}, B: struct {
				B []int `json:"b,omitempty"`
			}{B: []int{1}}},
		},
		{
			name: "HeadSliceMultiFieldsNotRootString",
			data: struct {
				A struct {
					A []int `json:"a,string"`
				}
				B struct {
					B []int `json:"b,string"`
				}
			}{A: struct {
				A []int `json:"a,string"`
			}{A: []int{-1}}, B: struct {
				B []int `json:"b,string"`
			}{B: []int{1}}},
		},

		// HeadSlicePtrMultiFieldsNotRoot
		{
			name: "HeadSlicePtrMultiFieldsNotRoot",
			data: struct {
				A struct {
					A *[]int `json:"a"`
				}
				B struct {
					B *[]int `json:"b"`
				}
			}{A: struct {
				A *[]int `json:"a"`
			}{A: sliceptr([]int{-1})}, B: struct {
				B *[]int `json:"b"`
			}{B: sliceptr([]int{1})}},
		},
		{
			name: "HeadSlicePtrMultiFieldsNotRootOmitEmpty",
			data: struct {
				A struct {
					A *[]int `json:"a,omitempty"`
				}
				B struct {
					B *[]int `json:"b,omitempty"`
				}
			}{A: struct {
				A *[]int `json:"a,omitempty"`
			}{A: sliceptr([]int{-1})}, B: struct {
				B *[]int `json:"b,omitempty"`
			}{B: sliceptr([]int{1})}},
		},
		{
			name: "HeadSlicePtrMultiFieldsNotRootString",
			data: struct {
				A struct {
					A *[]int `json:"a,string"`
				}
				B struct {
					B *[]int `json:"b,string"`
				}
			}{A: struct {
				A *[]int `json:"a,string"`
			}{A: sliceptr([]int{-1})}, B: struct {
				B *[]int `json:"b,string"`
			}{B: sliceptr([]int{1})}},
		},

		// HeadSlicePtrNilMultiFieldsNotRoot
		{
			name: "HeadSlicePtrNilMultiFieldsNotRoot",
			data: struct {
				A struct {
					A *[]int `json:"a"`
				}
				B struct {
					B *[]int `json:"b"`
				}
			}{A: struct {
				A *[]int `json:"a"`
			}{A: nil}, B: struct {
				B *[]int `json:"b"`
			}{B: nil}},
		},
		{
			name: "HeadSlicePtrNilMultiFieldsNotRootOmitEmpty",
			data: struct {
				A struct {
					A *[]int `json:"a,omitempty"`
				}
				B struct {
					B *[]int `json:"b,omitempty"`
				}
			}{A: struct {
				A *[]int `json:"a,omitempty"`
			}{A: nil}, B: struct {
				B *[]int `json:"b,omitempty"`
			}{B: nil}},
		},
		{
			name: "HeadSlicePtrNilMultiFieldsNotRootString",
			data: struct {
				A struct {
					A *[]int `json:"a,string"`
				}
				B struct {
					B *[]int `json:"b,string"`
				}
			}{A: struct {
				A *[]int `json:"a,string"`
			}{A: nil}, B: struct {
				B *[]int `json:"b,string"`
			}{B: nil}},
		},

		// PtrHeadSliceZeroMultiFieldsNotRoot
		{
			name: "PtrHeadSliceZeroMultiFieldsNotRoot",
			data: &struct {
				A struct {
					A []int `json:"a"`
				}
				B struct {
					B []int `json:"b"`
				}
			}{},
		},
		{
			name: "PtrHeadSliceZeroMultiFieldsNotRootOmitEmpty",
			data: &struct {
				A struct {
					A []int `json:"a,omitempty"`
				}
				B struct {
					B []int `json:"b,omitempty"`
				}
			}{},
		},
		{
			name: "PtrHeadSliceZeroMultiFieldsNotRootString",
			data: &struct {
				A struct {
					A []int `json:"a,string"`
				}
				B struct {
					B []int `json:"b,string"`
				}
			}{},
		},

		// PtrHeadSliceMultiFieldsNotRoot
		{
			name: "PtrHeadSliceMultiFieldsNotRoot",
			data: &struct {
				A struct {
					A []int `json:"a"`
				}
				B struct {
					B []int `json:"b"`
				}
			}{A: struct {
				A []int `json:"a"`
			}{A: []int{-1}}, B: struct {
				B []int `json:"b"`
			}{B: []int{1}}},
		},
		{
			name: "PtrHeadSliceMultiFieldsNotRootOmitEmpty",
			data: &struct {
				A struct {
					A []int `json:"a,omitempty"`
				}
				B struct {
					B []int `json:"b,omitempty"`
				}
			}{A: struct {
				A []int `json:"a,omitempty"`
			}{A: []int{-1}}, B: struct {
				B []int `json:"b,omitempty"`
			}{B: []int{1}}},
		},
		{
			name: "PtrHeadSliceMultiFieldsNotRootString",
			data: &struct {
				A struct {
					A []int `json:"a,string"`
				}
				B struct {
					B []int `json:"b,string"`
				}
			}{A: struct {
				A []int `json:"a,string"`
			}{A: []int{-1}}, B: struct {
				B []int `json:"b,string"`
			}{B: []int{1}}},
		},

		// PtrHeadSlicePtrMultiFieldsNotRoot
		{
			name: "PtrHeadSlicePtrMultiFieldsNotRoot",
			data: &struct {
				A *struct {
					A *[]int `json:"a"`
				}
				B *struct {
					B *[]int `json:"b"`
				}
			}{A: &(struct {
				A *[]int `json:"a"`
			}{A: sliceptr([]int{-1})}), B: &(struct {
				B *[]int `json:"b"`
			}{B: sliceptr([]int{1})})},
		},
		{
			name: "PtrHeadSlicePtrMultiFieldsNotRootOmitEmpty",
			data: &struct {
				A *struct {
					A *[]int `json:"a,omitempty"`
				}
				B *struct {
					B *[]int `json:"b,omitempty"`
				}
			}{A: &(struct {
				A *[]int `json:"a,omitempty"`
			}{A: sliceptr([]int{-1})}), B: &(struct {
				B *[]int `json:"b,omitempty"`
			}{B: sliceptr([]int{1})})},
		},
		{
			name: "PtrHeadSlicePtrMultiFieldsNotRootString",
			data: &struct {
				A *struct {
					A *[]int `json:"a,string"`
				}
				B *struct {
					B *[]int `json:"b,string"`
				}
			}{A: &(struct {
				A *[]int `json:"a,string"`
			}{A: sliceptr([]int{-1})}), B: &(struct {
				B *[]int `json:"b,string"`
			}{B: sliceptr([]int{1})})},
		},

		// PtrHeadSlicePtrNilMultiFieldsNotRoot
		{
			name: "PtrHeadSlicePtrNilMultiFieldsNotRoot",
			data: &struct {
				A *struct {
					A *[]int `json:"a"`
				}
				B *struct {
					B *[]int `json:"b"`
				}
			}{A: nil, B: nil},
		},
		{
			name: "PtrHeadSlicePtrNilMultiFieldsNotRootOmitEmpty",
			data: &struct {
				A *struct {
					A *[]int `json:"a,omitempty"`
				} `json:",omitempty"`
				B *struct {
					B *[]int `json:"b,omitempty"`
				} `json:",omitempty"`
			}{A: nil, B: nil},
		},
		{
			name: "PtrHeadSlicePtrNilMultiFieldsNotRootString",
			data: &struct {
				A *struct {
					A *[]int `json:"a,string"`
				} `json:",string"`
				B *struct {
					B *[]int `json:"b,string"`
				} `json:",string"`
			}{A: nil, B: nil},
		},

		// PtrHeadSliceNilMultiFieldsNotRoot
		{
			name: "PtrHeadSliceNilMultiFieldsNotRoot",
			data: (*struct {
				A *struct {
					A *[]int `json:"a"`
				}
				B *struct {
					B *[]int `json:"b"`
				}
			})(nil),
		},
		{
			name: "PtrHeadSliceNilMultiFieldsNotRootOmitEmpty",
			data: (*struct {
				A *struct {
					A *[]int `json:"a,omitempty"`
				}
				B *struct {
					B *[]int `json:"b,omitempty"`
				}
			})(nil),
		},
		{
			name: "PtrHeadSliceNilMultiFieldsNotRootString",
			data: (*struct {
				A *struct {
					A *[]int `json:"a,string"`
				}
				B *struct {
					B *[]int `json:"b,string"`
				}
			})(nil),
		},

		// PtrHeadSliceDoubleMultiFieldsNotRoot
		{
			name: "PtrHeadSliceDoubleMultiFieldsNotRoot",
			data: &struct {
				A *struct {
					A []int `json:"a"`
					B []int `json:"b"`
				}
				B *struct {
					A []int `json:"a"`
					B []int `json:"b"`
				}
			}{A: &(struct {
				A []int `json:"a"`
				B []int `json:"b"`
			}{A: []int{-1}, B: []int{1}}), B: &(struct {
				A []int `json:"a"`
				B []int `json:"b"`
			}{A: []int{-1}, B: nil})},
		},
		{
			name: "PtrHeadSliceDoubleMultiFieldsNotRootOmitEmpty",
			data: &struct {
				A *struct {
					A []int `json:"a,omitempty"`
					B []int `json:"b,omitempty"`
				}
				B *struct {
					A []int `json:"a,omitempty"`
					B []int `json:"b,omitempty"`
				}
			}{A: &(struct {
				A []int `json:"a,omitempty"`
				B []int `json:"b,omitempty"`
			}{A: []int{-1}, B: []int{1}}), B: &(struct {
				A []int `json:"a,omitempty"`
				B []int `json:"b,omitempty"`
			}{A: []int{-1}, B: nil})},
		},
		{
			name: "PtrHeadSliceDoubleMultiFieldsNotRootString",
			data: &struct {
				A *struct {
					A []int `json:"a,string"`
					B []int `json:"b,string"`
				}
				B *struct {
					A []int `json:"a,string"`
					B []int `json:"b,string"`
				}
			}{A: &(struct {
				A []int `json:"a,string"`
				B []int `json:"b,string"`
			}{A: []int{-1}, B: []int{1}}), B: &(struct {
				A []int `json:"a,string"`
				B []int `json:"b,string"`
			}{A: []int{-1}, B: nil})},
		},

		// PtrHeadSliceNilDoubleMultiFieldsNotRoot
		{
			name: "PtrHeadSliceNilDoubleMultiFieldsNotRoot",
			data: &struct {
				A *struct {
					A []int `json:"a"`
					B []int `json:"b"`
				}
				B *struct {
					A []int `json:"a"`
					B []int `json:"b"`
				}
			}{A: nil, B: nil},
		},
		{
			name: "PtrHeadSliceNilDoubleMultiFieldsNotRootOmitEmpty",
			data: &struct {
				A *struct {
					A []int `json:"a,omitempty"`
					B []int `json:"b,omitempty"`
				} `json:",omitempty"`
				B *struct {
					A []int `json:"a,omitempty"`
					B []int `json:"b,omitempty"`
				} `json:",omitempty"`
			}{A: nil, B: nil},
		},
		{
			name: "PtrHeadSliceNilDoubleMultiFieldsNotRootString",
			data: &struct {
				A *struct {
					A []int `json:"a,string"`
					B []int `json:"b,string"`
				}
				B *struct {
					A []int `json:"a,string"`
					B []int `json:"b,string"`
				}
			}{A: nil, B: nil},
		},

		// PtrHeadSliceNilDoubleMultiFieldsNotRoot
		{
			name: "PtrHeadSliceNilDoubleMultiFieldsNotRoot",
			data: (*struct {
				A *struct {
					A []int `json:"a"`
					B []int `json:"b"`
				}
				B *struct {
					A []int `json:"a"`
					B []int `json:"b"`
				}
			})(nil),
		},
		{
			name: "PtrHeadSliceNilDoubleMultiFieldsNotRootOmitEmpty",
			data: (*struct {
				A *struct {
					A []int `json:"a,omitempty"`
					B []int `json:"b,omitempty"`
				}
				B *struct {
					A []int `json:"a,omitempty"`
					B []int `json:"b,omitempty"`
				}
			})(nil),
		},
		{
			name: "PtrHeadSliceNilDoubleMultiFieldsNotRootString",
			data: (*struct {
				A *struct {
					A []int `json:"a,string"`
					B []int `json:"b,string"`
				}
				B *struct {
					A []int `json:"a,string"`
					B []int `json:"b,string"`
				}
			})(nil),
		},

		// PtrHeadSlicePtrDoubleMultiFieldsNotRoot
		{
			name: "PtrHeadSlicePtrDoubleMultiFieldsNotRoot",
			data: &struct {
				A *struct {
					A *[]int `json:"a"`
					B *[]int `json:"b"`
				}
				B *struct {
					A *[]int `json:"a"`
					B *[]int `json:"b"`
				}
			}{A: &(struct {
				A *[]int `json:"a"`
				B *[]int `json:"b"`
			}{A: sliceptr([]int{-1}), B: sliceptr([]int{1})}), B: &(struct {
				A *[]int `json:"a"`
				B *[]int `json:"b"`
			}{A: nil, B: nil})},
		},
		{
			name: "PtrHeadSlicePtrDoubleMultiFieldsNotRootOmitEmpty",
			data: &struct {
				A *struct {
					A *[]int `json:"a,omitempty"`
					B *[]int `json:"b,omitempty"`
				}
				B *struct {
					A *[]int `json:"a,omitempty"`
					B *[]int `json:"b,omitempty"`
				}
			}{A: &(struct {
				A *[]int `json:"a,omitempty"`
				B *[]int `json:"b,omitempty"`
			}{A: sliceptr([]int{-1}), B: sliceptr([]int{1})}), B: &(struct {
				A *[]int `json:"a,omitempty"`
				B *[]int `json:"b,omitempty"`
			}{A: nil, B: nil})},
		},
		{
			name: "PtrHeadSlicePtrDoubleMultiFieldsNotRootString",
			data: &struct {
				A *struct {
					A *[]int `json:"a,string"`
					B *[]int `json:"b,string"`
				}
				B *struct {
					A *[]int `json:"a,string"`
					B *[]int `json:"b,string"`
				}
			}{A: &(struct {
				A *[]int `json:"a,string"`
				B *[]int `json:"b,string"`
			}{A: sliceptr([]int{-1}), B: sliceptr([]int{1})}), B: &(struct {
				A *[]int `json:"a,string"`
				B *[]int `json:"b,string"`
			}{A: nil, B: nil})},
		},

		// PtrHeadSlicePtrNilDoubleMultiFieldsNotRoot
		{
			name: "PtrHeadSlicePtrNilDoubleMultiFieldsNotRoot",
			data: &struct {
				A *struct {
					A *[]int `json:"a"`
					B *[]int `json:"b"`
				}
				B *struct {
					A *[]int `json:"a"`
					B *[]int `json:"b"`
				}
			}{A: nil, B: nil},
		},
		{
			name: "PtrHeadSlicePtrNilDoubleMultiFieldsNotRootOmitEmpty",
			data: &struct {
				A *struct {
					A *[]int `json:"a,omitempty"`
					B *[]int `json:"b,omitempty"`
				} `json:",omitempty"`
				B *struct {
					A *[]int `json:"a,omitempty"`
					B *[]int `json:"b,omitempty"`
				} `json:",omitempty"`
			}{A: nil, B: nil},
		},
		{
			name: "PtrHeadSlicePtrNilDoubleMultiFieldsNotRootString",
			data: &struct {
				A *struct {
					A *[]int `json:"a,string"`
					B *[]int `json:"b,string"`
				}
				B *struct {
					A *[]int `json:"a,string"`
					B *[]int `json:"b,string"`
				}
			}{A: nil, B: nil},
		},

		// PtrHeadSlicePtrNilDoubleMultiFieldsNotRoot
		{
			name: "PtrHeadSlicePtrNilDoubleMultiFieldsNotRoot",
			data: (*struct {
				A *struct {
					A *[]int `json:"a"`
					B *[]int `json:"b"`
				}
				B *struct {
					A *[]int `json:"a"`
					B *[]int `json:"b"`
				}
			})(nil),
		},
		{
			name: "PtrHeadSlicePtrNilDoubleMultiFieldsNotRootOmitEmpty",
			data: (*struct {
				A *struct {
					A *[]int `json:"a,omitempty"`
					B *[]int `json:"b,omitempty"`
				}
				B *struct {
					A *[]int `json:"a,omitempty"`
					B *[]int `json:"b,omitempty"`
				}
			})(nil),
		},
		{
			name: "PtrHeadSlicePtrNilDoubleMultiFieldsNotRootString",
			data: (*struct {
				A *struct {
					A *[]int `json:"a,string"`
					B *[]int `json:"b,string"`
				}
				B *struct {
					A *[]int `json:"a,string"`
					B *[]int `json:"b,string"`
				}
			})(nil),
		},

		// AnonymousHeadSlice
		{
			name: "AnonymousHeadSlice",
			data: struct {
				structSlice
				B []int `json:"b"`
			}{
				structSlice: structSlice{A: []int{-1}},
				B:           nil,
			},
		},
		{
			name: "AnonymousHeadSliceOmitEmpty",
			data: struct {
				structSliceOmitEmpty
				B []int `json:"b,omitempty"`
			}{
				structSliceOmitEmpty: structSliceOmitEmpty{A: []int{-1}},
				B:                    nil,
			},
		},
		{
			name: "AnonymousHeadSliceString",
			data: struct {
				structSliceString
				B []int `json:"b,string"`
			}{
				structSliceString: structSliceString{A: []int{-1}},
				B:                 nil,
			},
		},

		// PtrAnonymousHeadSlice
		{
			name: "PtrAnonymousHeadSlice",
			data: struct {
				*structSlice
				B []int `json:"b"`
			}{
				structSlice: &structSlice{A: []int{-1}},
				B:           nil,
			},
		},
		{
			name: "PtrAnonymousHeadSliceOmitEmpty",
			data: struct {
				*structSliceOmitEmpty
				B []int `json:"b,omitempty"`
			}{
				structSliceOmitEmpty: &structSliceOmitEmpty{A: []int{-1}},
				B:                    nil,
			},
		},
		{
			name: "PtrAnonymousHeadSliceString",
			data: struct {
				*structSliceString
				B []int `json:"b,string"`
			}{
				structSliceString: &structSliceString{A: []int{-1}},
				B:                 nil,
			},
		},

		// PtrAnonymousHeadSliceNil
		{
			name: "PtrAnonymousHeadSliceNil",
			data: struct {
				*structSlice
				B []int `json:"b"`
			}{
				structSlice: &structSlice{A: nil},
				B:           nil,
			},
		},
		{
			name: "PtrAnonymousHeadSliceNilOmitEmpty",
			data: struct {
				*structSliceOmitEmpty
				B []int `json:"b,omitempty"`
			}{
				structSliceOmitEmpty: &structSliceOmitEmpty{A: nil},
				B:                    nil,
			},
		},
		{
			name: "PtrAnonymousHeadSliceNilString",
			data: struct {
				*structSliceString
				B []int `json:"b,string"`
			}{
				structSliceString: &structSliceString{A: nil},
				B:                 nil,
			},
		},

		// NilPtrAnonymousHeadSlice
		{
			name: "NilPtrAnonymousHeadSlice",
			data: struct {
				*structSlice
				B []int `json:"b"`
			}{
				structSlice: nil,
				B:           []int{-1},
			},
		},
		{
			name: "NilPtrAnonymousHeadSliceOmitEmpty",
			data: struct {
				*structSliceOmitEmpty
				B []int `json:"b,omitempty"`
			}{
				structSliceOmitEmpty: nil,
				B:                    []int{-1},
			},
		},
		{
			name: "NilPtrAnonymousHeadSliceString",
			data: struct {
				*structSliceString
				B []int `json:"b,string"`
			}{
				structSliceString: nil,
				B:                 []int{-1},
			},
		},

		// AnonymousHeadSlicePtr
		{
			name: "AnonymousHeadSlicePtr",
			data: struct {
				structSlicePtr
				B *[]int `json:"b"`
			}{
				structSlicePtr: structSlicePtr{A: sliceptr([]int{-1})},
				B:              nil,
			},
		},
		{
			name: "AnonymousHeadSlicePtrOmitEmpty",
			data: struct {
				structSlicePtrOmitEmpty
				B *[]int `json:"b,omitempty"`
			}{
				structSlicePtrOmitEmpty: structSlicePtrOmitEmpty{A: sliceptr([]int{-1})},
				B:                       nil,
			},
		},
		{
			name: "AnonymousHeadSlicePtrString",
			data: struct {
				structSlicePtrString
				B *[]int `json:"b,string"`
			}{
				structSlicePtrString: structSlicePtrString{A: sliceptr([]int{-1})},
				B:                    nil,
			},
		},

		// AnonymousHeadSlicePtrNil
		{
			name: "AnonymousHeadSlicePtrNil",
			data: struct {
				structSlicePtr
				B *[]int `json:"b"`
			}{
				structSlicePtr: structSlicePtr{A: nil},
				B:              sliceptr([]int{-1}),
			},
		},
		{
			name: "AnonymousHeadSlicePtrNilOmitEmpty",
			data: struct {
				structSlicePtrOmitEmpty
				B *[]int `json:"b,omitempty"`
			}{
				structSlicePtrOmitEmpty: structSlicePtrOmitEmpty{A: nil},
				B:                       sliceptr([]int{-1}),
			},
		},
		{
			name: "AnonymousHeadSlicePtrNilString",
			data: struct {
				structSlicePtrString
				B *[]int `json:"b,string"`
			}{
				structSlicePtrString: structSlicePtrString{A: nil},
				B:                    sliceptr([]int{-1}),
			},
		},

		// PtrAnonymousHeadSlicePtr
		{
			name: "PtrAnonymousHeadSlicePtr",
			data: struct {
				*structSlicePtr
				B *[]int `json:"b"`
			}{
				structSlicePtr: &structSlicePtr{A: sliceptr([]int{-1})},
				B:              nil,
			},
		},
		{
			name: "PtrAnonymousHeadSlicePtrOmitEmpty",
			data: struct {
				*structSlicePtrOmitEmpty
				B *[]int `json:"b,omitempty"`
			}{
				structSlicePtrOmitEmpty: &structSlicePtrOmitEmpty{A: sliceptr([]int{-1})},
				B:                       nil,
			},
		},
		{
			name: "PtrAnonymousHeadSlicePtrString",
			data: struct {
				*structSlicePtrString
				B *[]int `json:"b,string"`
			}{
				structSlicePtrString: &structSlicePtrString{A: sliceptr([]int{-1})},
				B:                    nil,
			},
		},

		// NilPtrAnonymousHeadSlicePtr
		{
			name: "NilPtrAnonymousHeadSlicePtr",
			data: struct {
				*structSlicePtr
				B *[]int `json:"b"`
			}{
				structSlicePtr: nil,
				B:              sliceptr([]int{-1}),
			},
		},
		{
			name: "NilPtrAnonymousHeadSlicePtrOmitEmpty",
			data: struct {
				*structSlicePtrOmitEmpty
				B *[]int `json:"b,omitempty"`
			}{
				structSlicePtrOmitEmpty: nil,
				B:                       sliceptr([]int{-1}),
			},
		},
		{
			name: "NilPtrAnonymousHeadSlicePtrString",
			data: struct {
				*structSlicePtrString
				B *[]int `json:"b,string"`
			}{
				structSlicePtrString: nil,
				B:                    sliceptr([]int{-1}),
			},
		},

		// AnonymousHeadSliceOnly
		{
			name: "AnonymousHeadSliceOnly",
			data: struct {
				structSlice
			}{
				structSlice: structSlice{A: []int{-1}},
			},
		},
		{
			name: "AnonymousHeadSliceOnlyOmitEmpty",
			data: struct {
				structSliceOmitEmpty
			}{
				structSliceOmitEmpty: structSliceOmitEmpty{A: []int{-1}},
			},
		},
		{
			name: "AnonymousHeadSliceOnlyString",
			data: struct {
				structSliceString
			}{
				structSliceString: structSliceString{A: []int{-1}},
			},
		},

		// PtrAnonymousHeadSliceOnly
		{
			name: "PtrAnonymousHeadSliceOnly",
			data: struct {
				*structSlice
			}{
				structSlice: &structSlice{A: []int{-1}},
			},
		},
		{
			name: "PtrAnonymousHeadSliceOnlyOmitEmpty",
			data: struct {
				*structSliceOmitEmpty
			}{
				structSliceOmitEmpty: &structSliceOmitEmpty{A: []int{-1}},
			},
		},
		{
			name: "PtrAnonymousHeadSliceOnlyString",
			data: struct {
				*structSliceString
			}{
				structSliceString: &structSliceString{A: []int{-1}},
			},
		},

		// NilPtrAnonymousHeadSliceOnly
		{
			name: "NilPtrAnonymousHeadSliceOnly",
			data: struct {
				*structSlice
			}{
				structSlice: nil,
			},
		},
		{
			name: "NilPtrAnonymousHeadSliceOnlyOmitEmpty",
			data: struct {
				*structSliceOmitEmpty
			}{
				structSliceOmitEmpty: nil,
			},
		},
		{
			name: "NilPtrAnonymousHeadSliceOnlyString",
			data: struct {
				*structSliceString
			}{
				structSliceString: nil,
			},
		},

		// AnonymousHeadSlicePtrOnly
		{
			name: "AnonymousHeadSlicePtrOnly",
			data: struct {
				structSlicePtr
			}{
				structSlicePtr: structSlicePtr{A: sliceptr([]int{-1})},
			},
		},
		{
			name: "AnonymousHeadSlicePtrOnlyOmitEmpty",
			data: struct {
				structSlicePtrOmitEmpty
			}{
				structSlicePtrOmitEmpty: structSlicePtrOmitEmpty{A: sliceptr([]int{-1})},
			},
		},
		{
			name: "AnonymousHeadSlicePtrOnlyString",
			data: struct {
				structSlicePtrString
			}{
				structSlicePtrString: structSlicePtrString{A: sliceptr([]int{-1})},
			},
		},

		// AnonymousHeadSlicePtrNilOnly
		{
			name: "AnonymousHeadSlicePtrNilOnly",
			data: struct {
				structSlicePtr
			}{
				structSlicePtr: structSlicePtr{A: nil},
			},
		},
		{
			name: "AnonymousHeadSlicePtrNilOnlyOmitEmpty",
			data: struct {
				structSlicePtrOmitEmpty
			}{
				structSlicePtrOmitEmpty: structSlicePtrOmitEmpty{A: nil},
			},
		},
		{
			name: "AnonymousHeadSlicePtrNilOnlyString",
			data: struct {
				structSlicePtrString
			}{
				structSlicePtrString: structSlicePtrString{A: nil},
			},
		},

		// PtrAnonymousHeadSlicePtrOnly
		{
			name: "PtrAnonymousHeadSlicePtrOnly",
			data: struct {
				*structSlicePtr
			}{
				structSlicePtr: &structSlicePtr{A: sliceptr([]int{-1})},
			},
		},
		{
			name: "PtrAnonymousHeadSlicePtrOnlyOmitEmpty",
			data: struct {
				*structSlicePtrOmitEmpty
			}{
				structSlicePtrOmitEmpty: &structSlicePtrOmitEmpty{A: sliceptr([]int{-1})},
			},
		},
		{
			name: "PtrAnonymousHeadSlicePtrOnlyString",
			data: struct {
				*structSlicePtrString
			}{
				structSlicePtrString: &structSlicePtrString{A: sliceptr([]int{-1})},
			},
		},

		// NilPtrAnonymousHeadSlicePtrOnly
		{
			name: "NilPtrAnonymousHeadSlicePtrOnly",
			data: struct {
				*structSlicePtr
			}{
				structSlicePtr: nil,
			},
		},
		{
			name: "NilPtrAnonymousHeadSlicePtrOnlyOmitEmpty",
			data: struct {
				*structSlicePtrOmitEmpty
			}{
				structSlicePtrOmitEmpty: nil,
			},
		},
		{
			name: "NilPtrAnonymousHeadSlicePtrOnlyString",
			data: struct {
				*structSlicePtrString
			}{
				structSlicePtrString: nil,
			},
		},
	}
	for _, test := range tests {
		for _, indent := range []bool{true, false} {
			for _, htmlEscape := range []bool{true, false} {
				t.Run(fmt.Sprintf("%s_indent_%t_escape_%t", test.name, indent, htmlEscape), func(t *testing.T) {
					var buf bytes.Buffer
					enc := json.NewEncoder(&buf)
					enc.SetEscapeHTML(htmlEscape)
					if indent {
						enc.SetIndent("", "  ")
					}
					if err := enc.Encode(test.data); err != nil {
						t.Fatalf("%s(htmlEscape:%v,indent:%v): %+v: %s", test.name, htmlEscape, indent, test.data, err)
					}
					stdresult := encodeByEncodingJSON(test.data, indent, htmlEscape)
					if buf.String() != stdresult {
						t.Errorf("%s(htmlEscape:%v,indent:%v): doesn't compatible with encoding/json. expected %q but got %q", test.name, htmlEscape, indent, stdresult, buf.String())
					}
				})
			}
		}
	}
}
