github.com/jxskiss/gopkg/v2@v2.14.9-0.20240514120614-899f3e7952b4/easy/json_test.go (about) 1 package easy 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "strings" 7 "testing" 8 9 "github.com/stretchr/testify/assert" 10 "github.com/tidwall/gjson" 11 ) 12 13 func TestJSONMarshalMapInterfaceInterface(t *testing.T) { 14 m := make(map[any]any) 15 m[1] = "1" 16 m["2"] = 2 17 got := JSON(m) 18 want := `{"1":"1","2":2}` 19 assert.Equal(t, want, got) 20 } 21 22 func TestJSONDisableEscapeHTML(t *testing.T) { 23 m := map[string]string{ 24 "html": "<html></html>", 25 } 26 27 stdRet, err := json.Marshal(m) 28 assert.Nil(t, err) 29 assert.Equal(t, `{"html":"\u003chtml\u003e\u003c/html\u003e"}`, string(stdRet)) 30 31 got := JSON(m) 32 assert.Equal(t, `{"html":"<html></html>"}`, got) 33 } 34 35 func TestLazyJSON(t *testing.T) { 36 var x = &testObject{A: 123, B: "abc"} 37 got1 := JSON(x) 38 got2 := fmt.Sprintf("%v", LazyJSON(x)) 39 assert.Equal(t, got1, got2) 40 } 41 42 func TestLasyFunc(t *testing.T) { 43 var x = &testObject{A: 123, B: "abc"} 44 got1 := Pretty2(x) 45 got2 := fmt.Sprint(LazyFunc(x, Pretty2)) 46 assert.Equal(t, got1, got2) 47 } 48 49 var prettyTestWant = strings.TrimSpace(` 50 { 51 "1": 123, 52 "b": "<html>" 53 }`) 54 55 func TestPretty(t *testing.T) { 56 test := map[string]any{ 57 "1": 123, 58 "b": "<html>", 59 } 60 jsonString := JSON(test) 61 assert.Equal(t, `{"1":123,"b":"<html>"}`, jsonString) 62 63 got1 := Pretty(test) 64 assert.Equal(t, prettyTestWant, got1) 65 66 got2 := Pretty(jsonString) 67 assert.Equal(t, prettyTestWant, got2) 68 69 test3 := []byte("<fff> not a json object") 70 got3 := Pretty(test3) 71 assert.Equal(t, string(test3), got3) 72 73 test4 := []byte{ 74 255, 253, 189, 240, 128, 200, 202, 204, 75 } 76 got4 := Pretty(test4) 77 assert.Equal(t, "<pretty: non-printable bytes of length 8>", got4) 78 79 got5 := Pretty2(map[string]any{"1": 123, "b": "<html>"}) 80 want5 := "{\n \"1\": 123,\n \"b\": \"<html>\"\n}" 81 assert.Equal(t, want5, got5) 82 } 83 84 var parseJSONRecordsTestData = ` 85 { 86 "files": [ 87 { 88 "displayName": "README.md", 89 "repoName": "gopkg", 90 "refName": "master", 91 "path": "README.md", 92 "preferredFileType": "readme", 93 "tabName": "README", 94 "loaded": true, 95 "timedOut": false, 96 "errorMessage": null, 97 "headerInfo": { 98 "toc": [ 99 { 100 "level": 1, 101 "text": "gopkg", 102 "anchor": "gopkg", 103 "htmlText": "gopkg" 104 }, 105 { 106 "level": 2, 107 "text": "Status", 108 "anchor": "status", 109 "htmlText": "Status" 110 }, 111 { 112 "level": 2, 113 "text": "Code layout", 114 "anchor": "code-layout", 115 "htmlText": "Code layout" 116 }, 117 { 118 "level": 2, 119 "text": "Packages", 120 "anchor": "packages", 121 "htmlText": "Packages" 122 } 123 ], 124 } 125 }, 126 { 127 "displayName": "LICENSE", 128 "repoName": "gopkg", 129 "refName": "master", 130 "path": "LICENSE", 131 "preferredFileType": "license", 132 "tabName": "License", 133 "loaded": true, 134 "timedOut": false, 135 "errorMessage": null, 136 "headerInfo": { 137 "toc": [], 138 } 139 } 140 ], 141 "processingTime": 31.543533999999998 142 }` 143 144 func TestParseJSONRecordsWithMapping(t *testing.T) { 145 mapping := JSONPathMapping{ 146 {"DisplayName", "displayName"}, 147 {"RepoName", "repoName"}, 148 {"Loaded", "loaded", "bool"}, 149 {"HeaderInfo", "headerInfo", "map"}, 150 {"HeaderInfoLevels", `headerInfo.toc.#(anchor="gopkg")#.level`, "array"}, 151 } 152 153 j := gjson.Parse(parseJSONRecordsTestData).Get("files") 154 got := ParseJSONRecordsWithMapping(j.Array(), mapping) 155 assert.Len(t, got, 2) 156 assert.Equal(t, "README.md", got[0]["DisplayName"]) 157 assert.Equal(t, "LICENSE", got[1]["DisplayName"]) 158 assert.Equal(t, true, got[0]["Loaded"]) 159 assert.Equal(t, true, got[1]["Loaded"]) 160 assert.Equal(t, 4, len(got[0]["HeaderInfo"].(map[string]any)["toc"].([]any))) 161 assert.Equal(t, 1, len(got[1]["HeaderInfo"].(map[string]any))) 162 assert.Equal(t, []any{float64(1)}, got[0]["HeaderInfoLevels"]) 163 assert.Equal(t, 0, len(got[1]["HeaderInfoLevels"].([]any))) 164 } 165 166 func TestParseJSONRecords(t *testing.T) { 167 type HeaderInfo struct { 168 Level int `mapping:"level"` 169 Text string `mapping:"text"` 170 } 171 type File struct { 172 DisplayName string `mapping:"displayName"` 173 RepoName string `mapping:"repoName"` 174 Loaded bool `mapping:"loaded"` 175 HeaderInfo_1 map[string]*HeaderInfo `mapping:"{\"toc\":headerInfo.toc.0}"` 176 HeaderInfo_2 map[string]map[string]any `mapping:"{\"toc\":headerInfo.toc.1}"` 177 HeaderInfoTOC_1 []*HeaderInfo `mapping:"headerInfo.toc"` 178 HeaderInfoTOC_2 []map[string]any `mapping:"headerInfo.toc"` 179 HeaderInfoLevels_1 []int `mapping:"headerInfo.toc.#(text=\"Code layout\")#.level"` 180 HeaderInfoLevels_2 []any `mapping:"headerInfo.toc.#(anchor=\"code-layout\")#.level"` 181 } 182 183 j := gjson.Parse(parseJSONRecordsTestData).Get("files") 184 185 var got []*File 186 err := ParseJSONRecords(&got, j.Array()) 187 assert.Nil(t, err) 188 assert.Len(t, got, 2) 189 190 assert.Equal(t, "README.md", got[0].DisplayName) 191 assert.Equal(t, "LICENSE", got[1].DisplayName) 192 assert.Equal(t, true, got[0].Loaded) 193 194 assert.Equal(t, 1, len(got[0].HeaderInfo_1)) 195 assert.Equal(t, HeaderInfo{1, "gopkg"}, *got[0].HeaderInfo_1["toc"]) 196 assert.Equal(t, 1, len(got[0].HeaderInfo_2)) 197 assert.Equal(t, 198 map[string]any{"level": float64(2), "text": "Status", "anchor": "status", "htmlText": "Status"}, 199 got[0].HeaderInfo_2["toc"]) 200 201 assert.Equal(t, 4, len(got[0].HeaderInfoTOC_1)) 202 assert.Equal(t, HeaderInfo{1, "gopkg"}, *got[0].HeaderInfoTOC_1[0]) 203 assert.Equal(t, 4, len(got[0].HeaderInfoTOC_2)) 204 assert.Equal(t, 205 map[string]any{"level": float64(2), "text": "Status", "anchor": "status", "htmlText": "Status"}, 206 got[0].HeaderInfoTOC_2[1], 207 ) 208 209 assert.Equal(t, []int{2}, got[0].HeaderInfoLevels_1) 210 assert.Equal(t, []any{float64(2)}, got[0].HeaderInfoLevels_2) 211 } 212 213 func TestTestParseJSONRecords_Options(t *testing.T) { 214 type HeaderInfo struct { 215 Level int `mapping:"__HeaderInfo_Level"` 216 Text string `mapping:"text"` 217 } 218 type File struct { 219 DisplayName string `mapping:"displayName"` 220 RepoName string `mapping:"repoName"` 221 Loaded bool `mapping:"loaded"` 222 HeaderInfo_1 map[string]*HeaderInfo 223 HeaderInfo_2 map[string]map[string]any `mapping:"__File_HeaderInfo_2"` 224 HeaderInfoLevels_1 []int 225 HeaderInfoLevels_2 []any `mapping:"__File_HeaderInfoLevels_2"` 226 } 227 228 j := gjson.Parse(parseJSONRecordsTestData).Get("files") 229 230 var got []*File 231 err := ParseJSONRecords(&got, j.Array(), 232 WithDynamicJSONMapping(map[string]string{ 233 "__HeaderInfo_Level": "level", 234 "HeaderInfo_1": `{"toc":headerInfo.toc.0}`, 235 "__File_HeaderInfo_2": `{"toc":headerInfo.toc.1}`, 236 "HeaderInfoLevels_1": `headerInfo.toc.#(text="Code layout")#.level`, 237 "__File_HeaderInfoLevels_2": fmt.Sprintf("headerInfo.toc.#(anchor=%q)#.level", "code-layout"), 238 })) 239 assert.Nil(t, err) 240 assert.Len(t, got, 2) 241 242 assert.Equal(t, 1, len(got[0].HeaderInfo_1)) 243 assert.Equal(t, HeaderInfo{1, "gopkg"}, *got[0].HeaderInfo_1["toc"]) 244 assert.Equal(t, 1, len(got[0].HeaderInfo_2)) 245 assert.Equal(t, 246 map[string]any{"level": float64(2), "text": "Status", "anchor": "status", "htmlText": "Status"}, 247 got[0].HeaderInfo_2["toc"]) 248 assert.Equal(t, []int{2}, got[0].HeaderInfoLevels_1) 249 assert.Equal(t, []any{float64(2)}, got[0].HeaderInfoLevels_2) 250 } 251 252 func TestParseJSONRecords_Recursive(t *testing.T) { 253 type Person struct { 254 A string 255 Parent *Person 256 Children1 []*Person `mapping:"Children_1"` 257 Children_2 map[string]*Person 258 } 259 testData := `[ 260 { 261 "A": "test", 262 "Parent": { 263 "A": "parent" 264 }, 265 "Children_1": [ 266 { 267 "A": "child_1", 268 "Parent": {"A": "test_child_1"} 269 }, 270 { 271 "A": "child_2", 272 "Parent": {"A": "test_child_2"}, 273 "Children_1": [ 274 {"A": "child_2_1"}, 275 {"A": "child_2_2"} 276 ] 277 } 278 ], 279 "Children_2": { 280 "child_1": { 281 "A": "child_1", 282 "Parent": {"A": "test_child_1"} 283 }, 284 "child_2": { 285 "A": "child_2", 286 "Parent": {"A": "test_child_2"}, 287 "Children_2": { 288 "child_2_1": {"A": "child_2_1"}, 289 "child_2_2": {"A": "child_2_2"} 290 } 291 } 292 } 293 } 294 ]` 295 var got []*Person 296 err := ParseJSONRecords(&got, gjson.Parse(testData).Array()) 297 assert.Nil(t, err) 298 assert.Len(t, got, 1) 299 300 assert.Equal(t, "test", got[0].A) 301 assert.Equal(t, "parent", got[0].Parent.A) 302 assert.Equal(t, ([]*Person)(nil), got[0].Parent.Children1) 303 assert.Equal(t, (map[string]*Person)(nil), got[0].Parent.Children_2) 304 305 assert.Equal(t, "child_1", got[0].Children1[0].A) 306 assert.Equal(t, "test_child_1", got[0].Children1[0].Parent.A) 307 assert.Equal(t, ([]*Person)(nil), got[0].Children1[0].Children1) 308 assert.Equal(t, (map[string]*Person)(nil), got[0].Children1[0].Children_2) 309 310 assert.Equal(t, 2, len(got[0].Children1)) 311 assert.Equal(t, "child_2", got[0].Children1[1].A) 312 assert.Equal(t, "test_child_2", got[0].Children1[1].Parent.A) 313 assert.Equal(t, 2, len(got[0].Children1[1].Children1)) 314 assert.Equal(t, (map[string]*Person)(nil), got[0].Children1[0].Children_2) 315 316 assert.Equal(t, 2, len(got[0].Children_2)) 317 assert.Equal(t, "child_1", got[0].Children_2["child_1"].A) 318 assert.Equal(t, "test_child_1", got[0].Children_2["child_1"].Parent.A) 319 assert.Equal(t, ([]*Person)(nil), got[0].Children_2["child_1"].Children1) 320 assert.Equal(t, (map[string]*Person)(nil), got[0].Children_2["child_1"].Children_2) 321 assert.Equal(t, "child_2", got[0].Children_2["child_2"].A) 322 assert.Equal(t, "test_child_2", got[0].Children_2["child_2"].Parent.A) 323 assert.Equal(t, "child_2_1", got[0].Children_2["child_2"].Children_2["child_2_1"].A) 324 assert.Equal(t, "child_2_2", got[0].Children_2["child_2"].Children_2["child_2_2"].A) 325 }