1
2
3
4
5
6
7
8 package jsontest
9
10 import (
11 "bytes"
12 "embed"
13 "errors"
14 "internal/zstd"
15 "io"
16 "io/fs"
17 "path"
18 "slices"
19 "strings"
20 "sync"
21 "time"
22 )
23
24
25
26
27
28
29 var testdataFS embed.FS
30
31 type Entry struct {
32 Name string
33 Data func() []byte
34 New func() any
35 }
36
37 func mustGet[T any](v T, err error) T {
38 if err != nil {
39 panic(err)
40 }
41 return v
42 }
43
44
45 var Data = func() (entries []Entry) {
46 fis := mustGet(fs.ReadDir(testdataFS, "testdata"))
47 slices.SortFunc(fis, func(x, y fs.DirEntry) int { return strings.Compare(x.Name(), y.Name()) })
48 for _, fi := range fis {
49 var entry Entry
50
51
52 words := strings.Split(strings.TrimSuffix(fi.Name(), ".json.zst"), "_")
53 for i := range words {
54 words[i] = strings.Title(words[i])
55 }
56 entry.Name = strings.Join(words, "")
57
58
59 entry.Data = sync.OnceValue(func() []byte {
60 filePath := path.Join("testdata", fi.Name())
61 b := mustGet(fs.ReadFile(testdataFS, filePath))
62 zr := zstd.NewReader(bytes.NewReader(b))
63 return mustGet(io.ReadAll(zr))
64 })
65
66
67 switch entry.Name {
68 case "CanadaGeometry":
69 entry.New = func() any { return new(canadaRoot) }
70 case "CitmCatalog":
71 entry.New = func() any { return new(citmRoot) }
72 case "GolangSource":
73 entry.New = func() any { return new(golangRoot) }
74 case "StringEscaped":
75 entry.New = func() any { return new(stringRoot) }
76 case "StringUnicode":
77 entry.New = func() any { return new(stringRoot) }
78 case "SyntheaFhir":
79 entry.New = func() any { return new(syntheaRoot) }
80 case "TwitterStatus":
81 entry.New = func() any { return new(twitterRoot) }
82 }
83
84 entries = append(entries, entry)
85 }
86 return entries
87 }()
88
89 type (
90 canadaRoot struct {
91 Type string `json:"type"`
92 Features []struct {
93 Type string `json:"type"`
94 Properties struct {
95 Name string `json:"name"`
96 } `json:"properties"`
97 Geometry struct {
98 Type string `json:"type"`
99 Coordinates [][][2]float64 `json:"coordinates"`
100 } `json:"geometry"`
101 } `json:"features"`
102 }
103 )
104
105 type (
106 citmRoot struct {
107 AreaNames map[int64]string `json:"areaNames"`
108 AudienceSubCategoryNames map[int64]string `json:"audienceSubCategoryNames"`
109 BlockNames map[int64]string `json:"blockNames"`
110 Events map[int64]struct {
111 Description string `json:"description"`
112 ID int `json:"id"`
113 Logo string `json:"logo"`
114 Name string `json:"name"`
115 SubTopicIds []int `json:"subTopicIds"`
116 SubjectCode any `json:"subjectCode"`
117 Subtitle any `json:"subtitle"`
118 TopicIds []int `json:"topicIds"`
119 } `json:"events"`
120 Performances []struct {
121 EventID int `json:"eventId"`
122 ID int `json:"id"`
123 Logo any `json:"logo"`
124 Name any `json:"name"`
125 Prices []struct {
126 Amount int `json:"amount"`
127 AudienceSubCategoryID int64 `json:"audienceSubCategoryId"`
128 SeatCategoryID int64 `json:"seatCategoryId"`
129 } `json:"prices"`
130 SeatCategories []struct {
131 Areas []struct {
132 AreaID int `json:"areaId"`
133 BlockIds []any `json:"blockIds"`
134 } `json:"areas"`
135 SeatCategoryID int `json:"seatCategoryId"`
136 } `json:"seatCategories"`
137 SeatMapImage any `json:"seatMapImage"`
138 Start int64 `json:"start"`
139 VenueCode string `json:"venueCode"`
140 } `json:"performances"`
141 SeatCategoryNames map[uint64]string `json:"seatCategoryNames"`
142 SubTopicNames map[uint64]string `json:"subTopicNames"`
143 SubjectNames map[uint64]string `json:"subjectNames"`
144 TopicNames map[uint64]string `json:"topicNames"`
145 TopicSubTopics map[uint64][]uint64 `json:"topicSubTopics"`
146 VenueNames map[string]string `json:"venueNames"`
147 }
148 )
149
150 type (
151 golangRoot struct {
152 Tree *golangNode `json:"tree"`
153 Username string `json:"username"`
154 }
155 golangNode struct {
156 Name string `json:"name"`
157 Kids []golangNode `json:"kids"`
158 CLWeight float64 `json:"cl_weight"`
159 Touches int `json:"touches"`
160 MinT uint64 `json:"min_t"`
161 MaxT uint64 `json:"max_t"`
162 MeanT uint64 `json:"mean_t"`
163 }
164 )
165
166 type (
167 stringRoot struct {
168 Arabic string `json:"Arabic"`
169 ArabicPresentationFormsA string `json:"Arabic Presentation Forms-A"`
170 ArabicPresentationFormsB string `json:"Arabic Presentation Forms-B"`
171 Armenian string `json:"Armenian"`
172 Arrows string `json:"Arrows"`
173 Bengali string `json:"Bengali"`
174 Bopomofo string `json:"Bopomofo"`
175 BoxDrawing string `json:"Box Drawing"`
176 CJKCompatibility string `json:"CJK Compatibility"`
177 CJKCompatibilityForms string `json:"CJK Compatibility Forms"`
178 CJKCompatibilityIdeographs string `json:"CJK Compatibility Ideographs"`
179 CJKSymbolsAndPunctuation string `json:"CJK Symbols and Punctuation"`
180 CJKUnifiedIdeographs string `json:"CJK Unified Ideographs"`
181 CJKUnifiedIdeographsExtensionA string `json:"CJK Unified Ideographs Extension A"`
182 CJKUnifiedIdeographsExtensionB string `json:"CJK Unified Ideographs Extension B"`
183 Cherokee string `json:"Cherokee"`
184 CurrencySymbols string `json:"Currency Symbols"`
185 Cyrillic string `json:"Cyrillic"`
186 CyrillicSupplementary string `json:"Cyrillic Supplementary"`
187 Devanagari string `json:"Devanagari"`
188 EnclosedAlphanumerics string `json:"Enclosed Alphanumerics"`
189 EnclosedCJKLettersAndMonths string `json:"Enclosed CJK Letters and Months"`
190 Ethiopic string `json:"Ethiopic"`
191 GeometricShapes string `json:"Geometric Shapes"`
192 Georgian string `json:"Georgian"`
193 GreekAndCoptic string `json:"Greek and Coptic"`
194 Gujarati string `json:"Gujarati"`
195 Gurmukhi string `json:"Gurmukhi"`
196 HangulCompatibilityJamo string `json:"Hangul Compatibility Jamo"`
197 HangulJamo string `json:"Hangul Jamo"`
198 HangulSyllables string `json:"Hangul Syllables"`
199 Hebrew string `json:"Hebrew"`
200 Hiragana string `json:"Hiragana"`
201 IPAExtentions string `json:"IPA Extentions"`
202 KangxiRadicals string `json:"Kangxi Radicals"`
203 Katakana string `json:"Katakana"`
204 Khmer string `json:"Khmer"`
205 KhmerSymbols string `json:"Khmer Symbols"`
206 Latin string `json:"Latin"`
207 LatinExtendedAdditional string `json:"Latin Extended Additional"`
208 Latin1Supplement string `json:"Latin-1 Supplement"`
209 LatinExtendedA string `json:"Latin-Extended A"`
210 LatinExtendedB string `json:"Latin-Extended B"`
211 LetterlikeSymbols string `json:"Letterlike Symbols"`
212 Malayalam string `json:"Malayalam"`
213 MathematicalAlphanumericSymbols string `json:"Mathematical Alphanumeric Symbols"`
214 MathematicalOperators string `json:"Mathematical Operators"`
215 MiscellaneousSymbols string `json:"Miscellaneous Symbols"`
216 Mongolian string `json:"Mongolian"`
217 NumberForms string `json:"Number Forms"`
218 Oriya string `json:"Oriya"`
219 PhoneticExtensions string `json:"Phonetic Extensions"`
220 SupplementalArrowsB string `json:"Supplemental Arrows-B"`
221 Syriac string `json:"Syriac"`
222 Tamil string `json:"Tamil"`
223 Thaana string `json:"Thaana"`
224 Thai string `json:"Thai"`
225 UnifiedCanadianAboriginalSyllabics string `json:"Unified Canadian Aboriginal Syllabics"`
226 YiRadicals string `json:"Yi Radicals"`
227 YiSyllables string `json:"Yi Syllables"`
228 }
229 )
230
231 type (
232 syntheaRoot struct {
233 Entry []struct {
234 FullURL string `json:"fullUrl"`
235 Request *struct {
236 Method string `json:"method"`
237 URL string `json:"url"`
238 } `json:"request"`
239 Resource *struct {
240 AbatementDateTime time.Time `json:"abatementDateTime"`
241 AchievementStatus syntheaCode `json:"achievementStatus"`
242 Active bool `json:"active"`
243 Activity []struct {
244 Detail *struct {
245 Code syntheaCode `json:"code"`
246 Location syntheaReference `json:"location"`
247 Status string `json:"status"`
248 } `json:"detail"`
249 } `json:"activity"`
250 Address []syntheaAddress `json:"address"`
251 Addresses []syntheaReference `json:"addresses"`
252 AuthoredOn time.Time `json:"authoredOn"`
253 BillablePeriod syntheaRange `json:"billablePeriod"`
254 BirthDate string `json:"birthDate"`
255 CareTeam []struct {
256 Provider syntheaReference `json:"provider"`
257 Reference string `json:"reference"`
258 Role syntheaCode `json:"role"`
259 Sequence int64 `json:"sequence"`
260 } `json:"careTeam"`
261 Category []syntheaCode `json:"category"`
262 Claim syntheaReference `json:"claim"`
263 Class syntheaCoding `json:"class"`
264 ClinicalStatus syntheaCode `json:"clinicalStatus"`
265 Code syntheaCode `json:"code"`
266 Communication []struct {
267 Language syntheaCode `json:"language"`
268 } `json:"communication"`
269 Component []struct {
270 Code syntheaCode `json:"code"`
271 ValueQuantity syntheaCoding `json:"valueQuantity"`
272 } `json:"component"`
273 Contained []struct {
274 Beneficiary syntheaReference `json:"beneficiary"`
275 ID string `json:"id"`
276 Intent string `json:"intent"`
277 Payor []syntheaReference `json:"payor"`
278 Performer []syntheaReference `json:"performer"`
279 Requester syntheaReference `json:"requester"`
280 ResourceType string `json:"resourceType"`
281 Status string `json:"status"`
282 Subject syntheaReference `json:"subject"`
283 Type syntheaCode `json:"type"`
284 } `json:"contained"`
285 Created time.Time `json:"created"`
286 DeceasedDateTime time.Time `json:"deceasedDateTime"`
287 Description syntheaCode `json:"description"`
288 Diagnosis []struct {
289 DiagnosisReference syntheaReference `json:"diagnosisReference"`
290 Sequence int64 `json:"sequence"`
291 Type []syntheaCode `json:"type"`
292 } `json:"diagnosis"`
293 DosageInstruction []struct {
294 AsNeededBoolean bool `json:"asNeededBoolean"`
295 DoseAndRate []struct {
296 DoseQuantity *struct {
297 Value float64 `json:"value"`
298 } `json:"doseQuantity"`
299 Type syntheaCode `json:"type"`
300 } `json:"doseAndRate"`
301 Sequence int64 `json:"sequence"`
302 Timing *struct {
303 Repeat *struct {
304 Frequency int64 `json:"frequency"`
305 Period float64 `json:"period"`
306 PeriodUnit string `json:"periodUnit"`
307 } `json:"repeat"`
308 } `json:"timing"`
309 } `json:"dosageInstruction"`
310 EffectiveDateTime time.Time `json:"effectiveDateTime"`
311 Encounter syntheaReference `json:"encounter"`
312 Extension []syntheaExtension `json:"extension"`
313 Gender string `json:"gender"`
314 Goal []syntheaReference `json:"goal"`
315 ID string `json:"id"`
316 Identifier []struct {
317 System string `json:"system"`
318 Type syntheaCode `json:"type"`
319 Use string `json:"use"`
320 Value string `json:"value"`
321 } `json:"identifier"`
322 Insurance []struct {
323 Coverage syntheaReference `json:"coverage"`
324 Focal bool `json:"focal"`
325 Sequence int64 `json:"sequence"`
326 } `json:"insurance"`
327 Insurer syntheaReference `json:"insurer"`
328 Intent string `json:"intent"`
329 Issued time.Time `json:"issued"`
330 Item []struct {
331 Adjudication []struct {
332 Amount syntheaCurrency `json:"amount"`
333 Category syntheaCode `json:"category"`
334 } `json:"adjudication"`
335 Category syntheaCode `json:"category"`
336 DiagnosisSequence []int64 `json:"diagnosisSequence"`
337 Encounter []syntheaReference `json:"encounter"`
338 InformationSequence []int64 `json:"informationSequence"`
339 LocationCodeableConcept syntheaCode `json:"locationCodeableConcept"`
340 Net syntheaCurrency `json:"net"`
341 ProcedureSequence []int64 `json:"procedureSequence"`
342 ProductOrService syntheaCode `json:"productOrService"`
343 Sequence int64 `json:"sequence"`
344 ServicedPeriod syntheaRange `json:"servicedPeriod"`
345 } `json:"item"`
346 LifecycleStatus string `json:"lifecycleStatus"`
347 ManagingOrganization []syntheaReference `json:"managingOrganization"`
348 MaritalStatus syntheaCode `json:"maritalStatus"`
349 MedicationCodeableConcept syntheaCode `json:"medicationCodeableConcept"`
350 MultipleBirthBoolean bool `json:"multipleBirthBoolean"`
351 Name rawValue `json:"name"`
352 NumberOfInstances int64 `json:"numberOfInstances"`
353 NumberOfSeries int64 `json:"numberOfSeries"`
354 OccurrenceDateTime time.Time `json:"occurrenceDateTime"`
355 OnsetDateTime time.Time `json:"onsetDateTime"`
356 Outcome string `json:"outcome"`
357 Participant []struct {
358 Individual syntheaReference `json:"individual"`
359 Member syntheaReference `json:"member"`
360 Role []syntheaCode `json:"role"`
361 } `json:"participant"`
362 Patient syntheaReference `json:"patient"`
363 Payment *struct {
364 Amount syntheaCurrency `json:"amount"`
365 } `json:"payment"`
366 PerformedPeriod syntheaRange `json:"performedPeriod"`
367 Period syntheaRange `json:"period"`
368 Prescription syntheaReference `json:"prescription"`
369 PrimarySource bool `json:"primarySource"`
370 Priority syntheaCode `json:"priority"`
371 Procedure []struct {
372 ProcedureReference syntheaReference `json:"procedureReference"`
373 Sequence int64 `json:"sequence"`
374 } `json:"procedure"`
375 Provider syntheaReference `json:"provider"`
376 ReasonCode []syntheaCode `json:"reasonCode"`
377 ReasonReference []syntheaReference `json:"reasonReference"`
378 RecordedDate time.Time `json:"recordedDate"`
379 Referral syntheaReference `json:"referral"`
380 Requester syntheaReference `json:"requester"`
381 ResourceType string `json:"resourceType"`
382 Result []syntheaReference `json:"result"`
383 Series []struct {
384 BodySite syntheaCoding `json:"bodySite"`
385 Instance []struct {
386 Number int64 `json:"number"`
387 SopClass syntheaCoding `json:"sopClass"`
388 Title string `json:"title"`
389 UID string `json:"uid"`
390 } `json:"instance"`
391 Modality syntheaCoding `json:"modality"`
392 Number int64 `json:"number"`
393 NumberOfInstances int64 `json:"numberOfInstances"`
394 Started string `json:"started"`
395 UID string `json:"uid"`
396 } `json:"series"`
397 ServiceProvider syntheaReference `json:"serviceProvider"`
398 Started time.Time `json:"started"`
399 Status string `json:"status"`
400 Subject syntheaReference `json:"subject"`
401 SupportingInfo []struct {
402 Category syntheaCode `json:"category"`
403 Sequence int64 `json:"sequence"`
404 ValueReference syntheaReference `json:"valueReference"`
405 } `json:"supportingInfo"`
406 Telecom []map[string]string `json:"telecom"`
407 Text map[string]string `json:"text"`
408 Total rawValue `json:"total"`
409 Type rawValue `json:"type"`
410 Use string `json:"use"`
411 VaccineCode syntheaCode `json:"vaccineCode"`
412 ValueCodeableConcept syntheaCode `json:"valueCodeableConcept"`
413 ValueQuantity syntheaCoding `json:"valueQuantity"`
414 VerificationStatus syntheaCode `json:"verificationStatus"`
415 } `json:"resource"`
416 } `json:"entry"`
417 ResourceType string `json:"resourceType"`
418 Type string `json:"type"`
419 }
420 syntheaCode struct {
421 Coding []syntheaCoding `json:"coding"`
422 Text string `json:"text"`
423 }
424 syntheaCoding struct {
425 Code string `json:"code"`
426 Display string `json:"display"`
427 System string `json:"system"`
428 Unit string `json:"unit"`
429 Value float64 `json:"value"`
430 }
431 syntheaReference struct {
432 Display string `json:"display"`
433 Reference string `json:"reference"`
434 }
435 syntheaAddress struct {
436 City string `json:"city"`
437 Country string `json:"country"`
438 Extension []syntheaExtension `json:"extension"`
439 Line []string `json:"line"`
440 PostalCode string `json:"postalCode"`
441 State string `json:"state"`
442 }
443 syntheaExtension struct {
444 URL string `json:"url"`
445 ValueAddress syntheaAddress `json:"valueAddress"`
446 ValueCode string `json:"valueCode"`
447 ValueDecimal float64 `json:"valueDecimal"`
448 ValueString string `json:"valueString"`
449 Extension []syntheaExtension `json:"extension"`
450 }
451 syntheaRange struct {
452 End time.Time `json:"end"`
453 Start time.Time `json:"start"`
454 }
455 syntheaCurrency struct {
456 Currency string `json:"currency"`
457 Value float64 `json:"value"`
458 }
459 )
460
461 type (
462 twitterRoot struct {
463 Statuses []twitterStatus `json:"statuses"`
464 SearchMetadata struct {
465 CompletedIn float64 `json:"completed_in"`
466 MaxID int64 `json:"max_id"`
467 MaxIDStr int64 `json:"max_id_str,string"`
468 NextResults string `json:"next_results"`
469 Query string `json:"query"`
470 RefreshURL string `json:"refresh_url"`
471 Count int `json:"count"`
472 SinceID int `json:"since_id"`
473 SinceIDStr int `json:"since_id_str,string"`
474 } `json:"search_metadata"`
475 }
476 twitterStatus struct {
477 Metadata struct {
478 ResultType string `json:"result_type"`
479 IsoLanguageCode string `json:"iso_language_code"`
480 } `json:"metadata"`
481 CreatedAt string `json:"created_at"`
482 ID int64 `json:"id"`
483 IDStr int64 `json:"id_str,string"`
484 Text string `json:"text"`
485 Source string `json:"source"`
486 Truncated bool `json:"truncated"`
487 InReplyToStatusID int64 `json:"in_reply_to_status_id"`
488 InReplyToStatusIDStr int64 `json:"in_reply_to_status_id_str,string"`
489 InReplyToUserID int64 `json:"in_reply_to_user_id"`
490 InReplyToUserIDStr int64 `json:"in_reply_to_user_id_str,string"`
491 InReplyToScreenName string `json:"in_reply_to_screen_name"`
492 User twitterUser `json:"user,omitempty"`
493 Geo any `json:"geo"`
494 Coordinates any `json:"coordinates"`
495 Place any `json:"place"`
496 Contributors any `json:"contributors"`
497 RetweeetedStatus *twitterStatus `json:"retweeted_status"`
498 RetweetCount int `json:"retweet_count"`
499 FavoriteCount int `json:"favorite_count"`
500 Entities twitterEntities `json:"entities,omitempty"`
501 Favorited bool `json:"favorited"`
502 Retweeted bool `json:"retweeted"`
503 PossiblySensitive bool `json:"possibly_sensitive"`
504 Lang string `json:"lang"`
505 }
506 twitterUser struct {
507 ID int64 `json:"id"`
508 IDStr string `json:"id_str"`
509 Name string `json:"name"`
510 ScreenName string `json:"screen_name"`
511 Location string `json:"location"`
512 Description string `json:"description"`
513 URL any `json:"url"`
514 Entities twitterEntities `json:"entities"`
515 Protected bool `json:"protected"`
516 FollowersCount int `json:"followers_count"`
517 FriendsCount int `json:"friends_count"`
518 ListedCount int `json:"listed_count"`
519 CreatedAt string `json:"created_at"`
520 FavouritesCount int `json:"favourites_count"`
521 UtcOffset int `json:"utc_offset"`
522 TimeZone string `json:"time_zone"`
523 GeoEnabled bool `json:"geo_enabled"`
524 Verified bool `json:"verified"`
525 StatusesCount int `json:"statuses_count"`
526 Lang string `json:"lang"`
527 ContributorsEnabled bool `json:"contributors_enabled"`
528 IsTranslator bool `json:"is_translator"`
529 IsTranslationEnabled bool `json:"is_translation_enabled"`
530 ProfileBackgroundColor string `json:"profile_background_color"`
531 ProfileBackgroundImageURL string `json:"profile_background_image_url"`
532 ProfileBackgroundImageURLHTTPS string `json:"profile_background_image_url_https"`
533 ProfileBackgroundTile bool `json:"profile_background_tile"`
534 ProfileImageURL string `json:"profile_image_url"`
535 ProfileImageURLHTTPS string `json:"profile_image_url_https"`
536 ProfileBannerURL string `json:"profile_banner_url"`
537 ProfileLinkColor string `json:"profile_link_color"`
538 ProfileSidebarBorderColor string `json:"profile_sidebar_border_color"`
539 ProfileSidebarFillColor string `json:"profile_sidebar_fill_color"`
540 ProfileTextColor string `json:"profile_text_color"`
541 ProfileUseBackgroundImage bool `json:"profile_use_background_image"`
542 DefaultProfile bool `json:"default_profile"`
543 DefaultProfileImage bool `json:"default_profile_image"`
544 Following bool `json:"following"`
545 FollowRequestSent bool `json:"follow_request_sent"`
546 Notifications bool `json:"notifications"`
547 }
548 twitterEntities struct {
549 Hashtags []any `json:"hashtags"`
550 Symbols []any `json:"symbols"`
551 URL *twitterURL `json:"url"`
552 URLs []twitterURL `json:"urls"`
553 UserMentions []struct {
554 ScreenName string `json:"screen_name"`
555 Name string `json:"name"`
556 ID int64 `json:"id"`
557 IDStr int64 `json:"id_str,string"`
558 Indices []int `json:"indices"`
559 } `json:"user_mentions"`
560 Description struct {
561 URLs []twitterURL `json:"urls"`
562 } `json:"description"`
563 Media []struct {
564 ID int64 `json:"id"`
565 IDStr string `json:"id_str"`
566 Indices []int `json:"indices"`
567 MediaURL string `json:"media_url"`
568 MediaURLHTTPS string `json:"media_url_https"`
569 URL string `json:"url"`
570 DisplayURL string `json:"display_url"`
571 ExpandedURL string `json:"expanded_url"`
572 Type string `json:"type"`
573 Sizes map[string]struct {
574 W int `json:"w"`
575 H int `json:"h"`
576 Resize string `json:"resize"`
577 } `json:"sizes"`
578 SourceStatusID int64 `json:"source_status_id"`
579 SourceStatusIDStr int64 `json:"source_status_id_str,string"`
580 } `json:"media"`
581 }
582 twitterURL struct {
583 URL string `json:"url"`
584 URLs []twitterURL `json:"urls"`
585 ExpandedURL string `json:"expanded_url"`
586 DisplayURL string `json:"display_url"`
587 Indices []int `json:"indices"`
588 }
589 )
590
591
592 type rawValue []byte
593
594 func (v rawValue) MarshalJSON() ([]byte, error) {
595 if v == nil {
596 return []byte("null"), nil
597 }
598 return v, nil
599 }
600
601 func (v *rawValue) UnmarshalJSON(b []byte) error {
602 if v == nil {
603 return errors.New("jsontest.rawValue: UnmarshalJSON on nil pointer")
604 }
605 *v = append((*v)[:0], b...)
606 return nil
607 }
608
View as plain text