// +build go1.18

/*
 * Copyright 2020 The Go Authors. All rights reserved.
 * Modifications Copyright 2022 ByteDance Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package generic_test

import (
    `bytes`
    `compress/gzip`
    `io/ioutil`
    `path/filepath`
    `sort`
    `strings`
    `sync`
    `time`
    `encoding/json`
)

type jsonTestdataEntry struct {
    name string
    data []byte
    val  any
    valI any
    new  func() any // nil if there is no concrete type for this
    newI func() any
}

var (
    jsonTestdataOnce sync.Once
    jsonTestdataLazy []jsonTestdataEntry
)

func jsonTestdata() []jsonTestdataEntry {
    jsonTestdataOnce.Do(func() {
        fis, err := ioutil.ReadDir("../testdata")
        if err != nil {
            panic(err)
        }
        sort.Slice(fis, func(i, j int) bool { return fis[i].Name() < fis[j].Name() })
        for _, fi := range fis {
            if !strings.HasSuffix(fi.Name(), ".json.gz") {
                continue
            }

            // Convert snake_case file name to CamelCase.
            words := strings.Split(strings.TrimSuffix(fi.Name(), ".json.gz"), "_")
            for i := range words {
                words[i] = strings.Title(words[i])
            }
            name := strings.Join(words, "")

            // Read and decompress the test data.
            b, err := ioutil.ReadFile(filepath.Join("../testdata", fi.Name()))
            if err != nil {
                panic(err)
            }
            zr, err := gzip.NewReader(bytes.NewReader(b))
            if err != nil {
                panic(err)
            }
            data, err := ioutil.ReadAll(zr)
            if err != nil {
                panic(err)
            }

            // Check whether there is a concrete type for this data.
            var newFn func() any
            switch name {
            case "CanadaGeometry":
                newFn = func() any { return new(canadaRoot) }
            case "CitmCatalog":
                newFn = func() any { return new(citmRoot) }
            case "GolangSource":
                newFn = func() any { return new(golangRoot) }
            case "StringEscaped":
                newFn = func() any { return new(stringRoot) }
            case "StringUnicode":
                newFn = func() any { return new(stringRoot) }
            case "SyntheaFhir":
                newFn = func() any { return new(syntheaRoot) }
            case "TwitterStatus":
                newFn = func() any { return new(twitterRoot) }
            }

            var newFnI = func() any { return new(any) }

            // Fill into value
            var val any = newFn()
            err = json.Unmarshal(data, val)
            if err != nil {
                panic(err)
            }
            var valI any = newFnI()
            err = json.Unmarshal(data, valI)
            if err != nil {
                panic(err)
            }
                        
            jsonTestdataLazy = append(jsonTestdataLazy, jsonTestdataEntry{name, data, val, valI, newFn, newFnI})
        }
    })
    return jsonTestdataLazy
}

type (
    canadaRoot struct {
        Type     string `json:"type"`
        Features []struct {
            Type       string `json:"type"`
            Properties struct {
                Name string `json:"name"`
            } `json:"properties"`
            Geometry struct {
                Type        string         `json:"type"`
                Coordinates [][][2]float64 `json:"coordinates"`
            } `json:"geometry"`
        } `json:"features"`
    }
)

type (
    citmRoot struct {
        AreaNames                map[int64]string `json:"areaNames"`
        AudienceSubCategoryNames map[int64]string `json:"audienceSubCategoryNames"`
        BlockNames               map[int64]string `json:"blockNames"`
        Events                   map[int64]struct {
            Description string `json:"description"`
            ID          int    `json:"id"`
            Logo        string `json:"logo"`
            Name        string `json:"name"`
            SubTopicIds []int  `json:"subTopicIds"`
            SubjectCode any    `json:"subjectCode"`
            Subtitle    any    `json:"subtitle"`
            TopicIds    []int  `json:"topicIds"`
        } `json:"events"`
        Performances []struct {
            EventID int `json:"eventId"`
            ID      int `json:"id"`
            Logo    any `json:"logo"`
            Name    any `json:"name"`
            Prices  []struct {
                Amount                int   `json:"amount"`
                AudienceSubCategoryID int64 `json:"audienceSubCategoryId"`
                SeatCategoryID        int64 `json:"seatCategoryId"`
            } `json:"prices"`
            SeatCategories []struct {
                Areas []struct {
                    AreaID   int   `json:"areaId"`
                    BlockIds []any `json:"blockIds"`
                } `json:"areas"`
                SeatCategoryID int `json:"seatCategoryId"`
            } `json:"seatCategories"`
            SeatMapImage any    `json:"seatMapImage"`
            Start        int64  `json:"start"`
            VenueCode    string `json:"venueCode"`
        } `json:"performances"`
        SeatCategoryNames map[uint64]string   `json:"seatCategoryNames"`
        SubTopicNames     map[uint64]string   `json:"subTopicNames"`
        SubjectNames      map[uint64]string   `json:"subjectNames"`
        TopicNames        map[uint64]string   `json:"topicNames"`
        TopicSubTopics    map[uint64][]uint64 `json:"topicSubTopics"`
        VenueNames        map[string]string   `json:"venueNames"`
    }
)

type (
    golangRoot struct {
        Tree     *golangNode `json:"tree"`
        Username string      `json:"username"`
    }
    golangNode struct {
        Name     string       `json:"name"`
        Kids     []golangNode `json:"kids"`
        CLWeight float64      `json:"cl_weight"`
        Touches  int          `json:"touches"`
        MinT     uint64       `json:"min_t"`
        MaxT     uint64       `json:"max_t"`
        MeanT    uint64       `json:"mean_t"`
    }
)

type (
    stringRoot struct {
        Arabic                             string `json:"Arabic"`
        ArabicPresentationFormsA           string `json:"Arabic Presentation Forms-A"`
        ArabicPresentationFormsB           string `json:"Arabic Presentation Forms-B"`
        Armenian                           string `json:"Armenian"`
        Arrows                             string `json:"Arrows"`
        Bengali                            string `json:"Bengali"`
        Bopomofo                           string `json:"Bopomofo"`
        BoxDrawing                         string `json:"Box Drawing"`
        CJKCompatibility                   string `json:"CJK Compatibility"`
        CJKCompatibilityForms              string `json:"CJK Compatibility Forms"`
        CJKCompatibilityIdeographs         string `json:"CJK Compatibility Ideographs"`
        CJKSymbolsAndPunctuation           string `json:"CJK Symbols and Punctuation"`
        CJKUnifiedIdeographs               string `json:"CJK Unified Ideographs"`
        CJKUnifiedIdeographsExtensionA     string `json:"CJK Unified Ideographs Extension A"`
        CJKUnifiedIdeographsExtensionB     string `json:"CJK Unified Ideographs Extension B"`
        Cherokee                           string `json:"Cherokee"`
        CurrencySymbols                    string `json:"Currency Symbols"`
        Cyrillic                           string `json:"Cyrillic"`
        CyrillicSupplementary              string `json:"Cyrillic Supplementary"`
        Devanagari                         string `json:"Devanagari"`
        EnclosedAlphanumerics              string `json:"Enclosed Alphanumerics"`
        EnclosedCJKLettersAndMonths        string `json:"Enclosed CJK Letters and Months"`
        Ethiopic                           string `json:"Ethiopic"`
        GeometricShapes                    string `json:"Geometric Shapes"`
        Georgian                           string `json:"Georgian"`
        GreekAndCoptic                     string `json:"Greek and Coptic"`
        Gujarati                           string `json:"Gujarati"`
        Gurmukhi                           string `json:"Gurmukhi"`
        HangulCompatibilityJamo            string `json:"Hangul Compatibility Jamo"`
        HangulJamo                         string `json:"Hangul Jamo"`
        HangulSyllables                    string `json:"Hangul Syllables"`
        Hebrew                             string `json:"Hebrew"`
        Hiragana                           string `json:"Hiragana"`
        IPAExtentions                      string `json:"IPA Extentions"`
        KangxiRadicals                     string `json:"Kangxi Radicals"`
        Katakana                           string `json:"Katakana"`
        Khmer                              string `json:"Khmer"`
        KhmerSymbols                       string `json:"Khmer Symbols"`
        Latin                              string `json:"Latin"`
        LatinExtendedAdditional            string `json:"Latin Extended Additional"`
        Latin1Supplement                   string `json:"Latin-1 Supplement"`
        LatinExtendedA                     string `json:"Latin-Extended A"`
        LatinExtendedB                     string `json:"Latin-Extended B"`
        LetterlikeSymbols                  string `json:"Letterlike Symbols"`
        Malayalam                          string `json:"Malayalam"`
        MathematicalAlphanumericSymbols    string `json:"Mathematical Alphanumeric Symbols"`
        MathematicalOperators              string `json:"Mathematical Operators"`
        MiscellaneousSymbols               string `json:"Miscellaneous Symbols"`
        Mongolian                          string `json:"Mongolian"`
        NumberForms                        string `json:"Number Forms"`
        Oriya                              string `json:"Oriya"`
        PhoneticExtensions                 string `json:"Phonetic Extensions"`
        SupplementalArrowsB                string `json:"Supplemental Arrows-B"`
        Syriac                             string `json:"Syriac"`
        Tamil                              string `json:"Tamil"`
        Thaana                             string `json:"Thaana"`
        Thai                               string `json:"Thai"`
        UnifiedCanadianAboriginalSyllabics string `json:"Unified Canadian Aboriginal Syllabics"`
        YiRadicals                         string `json:"Yi Radicals"`
        YiSyllables                        string `json:"Yi Syllables"`
    }
)

type (
    syntheaRoot struct {
        Entry []struct {
            FullURL string `json:"fullUrl"`
            Request *struct {
                Method string `json:"method"`
                URL    string `json:"url"`
            } `json:"request"`
            Resource *struct {
                AbatementDateTime time.Time   `json:"abatementDateTime"`
                AchievementStatus syntheaCode `json:"achievementStatus"`
                Active            bool        `json:"active"`
                Activity          []struct {
                    Detail *struct {
                        Code     syntheaCode      `json:"code"`
                        Location syntheaReference `json:"location"`
                        Status   string           `json:"status"`
                    } `json:"detail"`
                } `json:"activity"`
                Address        []syntheaAddress   `json:"address"`
                Addresses      []syntheaReference `json:"addresses"`
                AuthoredOn     time.Time          `json:"authoredOn"`
                BillablePeriod syntheaRange       `json:"billablePeriod"`
                BirthDate      string             `json:"birthDate"`
                CareTeam       []struct {
                    Provider  syntheaReference `json:"provider"`
                    Reference string           `json:"reference"`
                    Role      syntheaCode      `json:"role"`
                    Sequence  int64            `json:"sequence"`
                } `json:"careTeam"`
                Category       []syntheaCode    `json:"category"`
                Claim          syntheaReference `json:"claim"`
                Class          syntheaCoding    `json:"class"`
                ClinicalStatus syntheaCode      `json:"clinicalStatus"`
                Code           syntheaCode      `json:"code"`
                Communication  []struct {
                    Language syntheaCode `json:"language"`
                } `json:"communication"`
                Component []struct {
                    Code          syntheaCode   `json:"code"`
                    ValueQuantity syntheaCoding `json:"valueQuantity"`
                } `json:"component"`
                Contained []struct {
                    Beneficiary  syntheaReference   `json:"beneficiary"`
                    ID           string             `json:"id"`
                    Intent       string             `json:"intent"`
                    Payor        []syntheaReference `json:"payor"`
                    Performer    []syntheaReference `json:"performer"`
                    Requester    syntheaReference   `json:"requester"`
                    ResourceType string             `json:"resourceType"`
                    Status       string             `json:"status"`
                    Subject      syntheaReference   `json:"subject"`
                    Type         syntheaCode        `json:"type"`
                } `json:"contained"`
                Created          time.Time   `json:"created"`
                DeceasedDateTime time.Time   `json:"deceasedDateTime"`
                Description      syntheaCode `json:"description"`
                Diagnosis        []struct {
                    DiagnosisReference syntheaReference `json:"diagnosisReference"`
                    Sequence           int64            `json:"sequence"`
                    Type               []syntheaCode    `json:"type"`
                } `json:"diagnosis"`
                DosageInstruction []struct {
                    AsNeededBoolean bool `json:"asNeededBoolean"`
                    DoseAndRate     []struct {
                        DoseQuantity *struct {
                            Value float64 `json:"value"`
                        } `json:"doseQuantity"`
                        Type syntheaCode `json:"type"`
                    } `json:"doseAndRate"`
                    Sequence int64 `json:"sequence"`
                    Timing   *struct {
                        Repeat *struct {
                            Frequency  int64   `json:"frequency"`
                            Period     float64 `json:"period"`
                            PeriodUnit string  `json:"periodUnit"`
                        } `json:"repeat"`
                    } `json:"timing"`
                } `json:"dosageInstruction"`
                EffectiveDateTime time.Time          `json:"effectiveDateTime"`
                Encounter         syntheaReference   `json:"encounter"`
                Extension         []syntheaExtension `json:"extension"`
                Gender            string             `json:"gender"`
                Goal              []syntheaReference `json:"goal"`
                ID                string             `json:"id"`
                Identifier        []struct {
                    System string      `json:"system"`
                    Type   syntheaCode `json:"type"`
                    Use    string      `json:"use"`
                    Value  string      `json:"value"`
                } `json:"identifier"`
                Insurance []struct {
                    Coverage syntheaReference `json:"coverage"`
                    Focal    bool             `json:"focal"`
                    Sequence int64            `json:"sequence"`
                } `json:"insurance"`
                Insurer syntheaReference `json:"insurer"`
                Intent  string           `json:"intent"`
                Issued  time.Time        `json:"issued"`
                Item    []struct {
                    Adjudication []struct {
                        Amount   syntheaCurrency `json:"amount"`
                        Category syntheaCode     `json:"category"`
                    } `json:"adjudication"`
                    Category                syntheaCode        `json:"category"`
                    DiagnosisSequence       []int64            `json:"diagnosisSequence"`
                    Encounter               []syntheaReference `json:"encounter"`
                    InformationSequence     []int64            `json:"informationSequence"`
                    LocationCodeableConcept syntheaCode        `json:"locationCodeableConcept"`
                    Net                     syntheaCurrency    `json:"net"`
                    ProcedureSequence       []int64            `json:"procedureSequence"`
                    ProductOrService        syntheaCode        `json:"productOrService"`
                    Sequence                int64              `json:"sequence"`
                    ServicedPeriod          syntheaRange       `json:"servicedPeriod"`
                } `json:"item"`
                LifecycleStatus           string             `json:"lifecycleStatus"`
                ManagingOrganization      []syntheaReference `json:"managingOrganization"`
                MaritalStatus             syntheaCode        `json:"maritalStatus"`
                MedicationCodeableConcept syntheaCode        `json:"medicationCodeableConcept"`
                MultipleBirthBoolean      bool               `json:"multipleBirthBoolean"`
                Name                      json.RawMessage           `json:"name"`
                NumberOfInstances         int64              `json:"numberOfInstances"`
                NumberOfSeries            int64              `json:"numberOfSeries"`
                OccurrenceDateTime        time.Time          `json:"occurrenceDateTime"`
                OnsetDateTime             time.Time          `json:"onsetDateTime"`
                Outcome                   string             `json:"outcome"`
                Participant               []struct {
                    Individual syntheaReference `json:"individual"`
                    Member     syntheaReference `json:"member"`
                    Role       []syntheaCode    `json:"role"`
                } `json:"participant"`
                Patient syntheaReference `json:"patient"`
                Payment *struct {
                    Amount syntheaCurrency `json:"amount"`
                } `json:"payment"`
                PerformedPeriod syntheaRange     `json:"performedPeriod"`
                Period          syntheaRange     `json:"period"`
                Prescription    syntheaReference `json:"prescription"`
                PrimarySource   bool             `json:"primarySource"`
                Priority        syntheaCode      `json:"priority"`
                Procedure       []struct {
                    ProcedureReference syntheaReference `json:"procedureReference"`
                    Sequence           int64            `json:"sequence"`
                } `json:"procedure"`
                Provider        syntheaReference   `json:"provider"`
                ReasonCode      []syntheaCode      `json:"reasonCode"`
                ReasonReference []syntheaReference `json:"reasonReference"`
                RecordedDate    time.Time          `json:"recordedDate"`
                Referral        syntheaReference   `json:"referral"`
                Requester       syntheaReference   `json:"requester"`
                ResourceType    string             `json:"resourceType"`
                Result          []syntheaReference `json:"result"`
                Series          []struct {
                    BodySite syntheaCoding `json:"bodySite"`
                    Instance []struct {
                        Number   int64         `json:"number"`
                        SopClass syntheaCoding `json:"sopClass"`
                        Title    string        `json:"title"`
                        UID      string        `json:"uid"`
                    } `json:"instance"`
                    Modality          syntheaCoding `json:"modality"`
                    Number            int64         `json:"number"`
                    NumberOfInstances int64         `json:"numberOfInstances"`
                    Started           string        `json:"started"`
                    UID               string        `json:"uid"`
                } `json:"series"`
                ServiceProvider syntheaReference `json:"serviceProvider"`
                Started         time.Time        `json:"started"`
                Status          string           `json:"status"`
                Subject         syntheaReference `json:"subject"`
                SupportingInfo  []struct {
                    Category       syntheaCode      `json:"category"`
                    Sequence       int64            `json:"sequence"`
                    ValueReference syntheaReference `json:"valueReference"`
                } `json:"supportingInfo"`
                Telecom              []map[string]string `json:"telecom"`
                Text                 map[string]string   `json:"text"`
                Total                json.RawMessage            `json:"total"`
                Type                 json.RawMessage            `json:"type"`
                Use                  string              `json:"use"`
                VaccineCode          syntheaCode         `json:"vaccineCode"`
                ValueCodeableConcept syntheaCode         `json:"valueCodeableConcept"`
                ValueQuantity        syntheaCoding       `json:"valueQuantity"`
                VerificationStatus   syntheaCode         `json:"verificationStatus"`
            } `json:"resource"`
        } `json:"entry"`
        ResourceType string `json:"resourceType"`
        Type         string `json:"type"`
    }
    syntheaCode struct {
        Coding []syntheaCoding `json:"coding"`
        Text   string          `json:"text"`
    }
    syntheaCoding struct {
        Code    string  `json:"code"`
        Display string  `json:"display"`
        System  string  `json:"system"`
        Unit    string  `json:"unit"`
        Value   float64 `json:"value"`
    }
    syntheaReference struct {
        Display   string `json:"display"`
        Reference string `json:"reference"`
    }
    syntheaAddress struct {
        City       string             `json:"city"`
        Country    string             `json:"country"`
        Extension  []syntheaExtension `json:"extension"`
        Line       []string           `json:"line"`
        PostalCode string             `json:"postalCode"`
        State      string             `json:"state"`
    }
    syntheaExtension struct {
        URL          string             `json:"url"`
        ValueAddress syntheaAddress     `json:"valueAddress"`
        ValueCode    string             `json:"valueCode"`
        ValueDecimal float64            `json:"valueDecimal"`
        ValueString  string             `json:"valueString"`
        Extension    []syntheaExtension `json:"extension"`
    }
    syntheaRange struct {
        End   time.Time `json:"end"`
        Start time.Time `json:"start"`
    }
    syntheaCurrency struct {
        Currency string  `json:"currency"`
        Value    float64 `json:"value"`
    }
)

type (
    twitterRoot struct {
        Statuses       []twitterStatus `json:"statuses"`
        SearchMetadata struct {
            CompletedIn float64 `json:"completed_in"`
            MaxID       int64   `json:"max_id"`
            MaxIDStr    int64   `json:"max_id_str,string"`
            NextResults string  `json:"next_results"`
            Query       string  `json:"query"`
            RefreshURL  string  `json:"refresh_url"`
            Count       int     `json:"count"`
            SinceID     int     `json:"since_id"`
            SinceIDStr  int     `json:"since_id_str,string"`
        } `json:"search_metadata"`
    }
    twitterStatus struct {
        Metadata struct {
            ResultType      string `json:"result_type"`
            IsoLanguageCode string `json:"iso_language_code"`
        } `json:"metadata"`
        CreatedAt            string          `json:"created_at"`
        ID                   int64           `json:"id"`
        IDStr                int64           `json:"id_str,string"`
        Text                 string          `json:"text"`
        Source               string          `json:"source"`
        Truncated            bool            `json:"truncated"`
        InReplyToStatusID    int64           `json:"in_reply_to_status_id"`
        InReplyToStatusIDStr int64           `json:"in_reply_to_status_id_str,string"`
        InReplyToUserID      int64           `json:"in_reply_to_user_id"`
        InReplyToUserIDStr   int64           `json:"in_reply_to_user_id_str,string"`
        InReplyToScreenName  string          `json:"in_reply_to_screen_name"`
        User                 twitterUser     `json:"user,omitempty"`
        Geo                  any             `json:"geo"`
        Coordinates          any             `json:"coordinates"`
        Place                any             `json:"place"`
        Contributors         any             `json:"contributors"`
        RetweeetedStatus     *twitterStatus  `json:"retweeted_status"`
        RetweetCount         int             `json:"retweet_count"`
        FavoriteCount        int             `json:"favorite_count"`
        Entities             twitterEntities `json:"entities,omitempty"`
        Favorited            bool            `json:"favorited"`
        Retweeted            bool            `json:"retweeted"`
        PossiblySensitive    bool            `json:"possibly_sensitive"`
        Lang                 string          `json:"lang"`
    }
    twitterUser struct {
        ID                             int64           `json:"id"`
        IDStr                          string          `json:"id_str"`
        Name                           string          `json:"name"`
        ScreenName                     string          `json:"screen_name"`
        Location                       string          `json:"location"`
        Description                    string          `json:"description"`
        URL                            any             `json:"url"`
        Entities                       twitterEntities `json:"entities"`
        Protected                      bool            `json:"protected"`
        FollowersCount                 int             `json:"followers_count"`
        FriendsCount                   int             `json:"friends_count"`
        ListedCount                    int             `json:"listed_count"`
        CreatedAt                      string          `json:"created_at"`
        FavouritesCount                int             `json:"favourites_count"`
        UtcOffset                      int             `json:"utc_offset"`
        TimeZone                       string          `json:"time_zone"`
        GeoEnabled                     bool            `json:"geo_enabled"`
        Verified                       bool            `json:"verified"`
        StatusesCount                  int             `json:"statuses_count"`
        Lang                           string          `json:"lang"`
        ContributorsEnabled            bool            `json:"contributors_enabled"`
        IsTranslator                   bool            `json:"is_translator"`
        IsTranslationEnabled           bool            `json:"is_translation_enabled"`
        ProfileBackgroundColor         string          `json:"profile_background_color"`
        ProfileBackgroundImageURL      string          `json:"profile_background_image_url"`
        ProfileBackgroundImageURLHTTPS string          `json:"profile_background_image_url_https"`
        ProfileBackgroundTile          bool            `json:"profile_background_tile"`
        ProfileImageURL                string          `json:"profile_image_url"`
        ProfileImageURLHTTPS           string          `json:"profile_image_url_https"`
        ProfileBannerURL               string          `json:"profile_banner_url"`
        ProfileLinkColor               string          `json:"profile_link_color"`
        ProfileSidebarBorderColor      string          `json:"profile_sidebar_border_color"`
        ProfileSidebarFillColor        string          `json:"profile_sidebar_fill_color"`
        ProfileTextColor               string          `json:"profile_text_color"`
        ProfileUseBackgroundImage      bool            `json:"profile_use_background_image"`
        DefaultProfile                 bool            `json:"default_profile"`
        DefaultProfileImage            bool            `json:"default_profile_image"`
        Following                      bool            `json:"following"`
        FollowRequestSent              bool            `json:"follow_request_sent"`
        Notifications                  bool            `json:"notifications"`
    }
    twitterEntities struct {
        Hashtags     []any        `json:"hashtags"`
        Symbols      []any        `json:"symbols"`
        URL          *twitterURL  `json:"url"`
        URLs         []twitterURL `json:"urls"`
        UserMentions []struct {
            ScreenName string `json:"screen_name"`
            Name       string `json:"name"`
            ID         int64  `json:"id"`
            IDStr      int64  `json:"id_str,string"`
            Indices    []int  `json:"indices"`
        } `json:"user_mentions"`
        Description struct {
            URLs []twitterURL `json:"urls"`
        } `json:"description"`
        Media []struct {
            ID            int64  `json:"id"`
            IDStr         string `json:"id_str"`
            Indices       []int  `json:"indices"`
            MediaURL      string `json:"media_url"`
            MediaURLHTTPS string `json:"media_url_https"`
            URL           string `json:"url"`
            DisplayURL    string `json:"display_url"`
            ExpandedURL   string `json:"expanded_url"`
            Type          string `json:"type"`
            Sizes         map[string]struct {
                W      int    `json:"w"`
                H      int    `json:"h"`
                Resize string `json:"resize"`
            } `json:"sizes"`
            SourceStatusID    int64 `json:"source_status_id"`
            SourceStatusIDStr int64 `json:"source_status_id_str,string"`
        } `json:"media"`
    }
    twitterURL struct {
        URL         string       `json:"url"`
        URLs        []twitterURL `json:"urls"`
        ExpandedURL string       `json:"expanded_url"`
        DisplayURL  string       `json:"display_url"`
        Indices     []int        `json:"indices"`
    }
)