@@ -27,18 +27,35 @@ import (
2727// Parser contains the logic to parse the JSON from the web-features Github Release.
2828type Parser struct {}
2929
30+ // V3Parser contains the logic to parse the JSON from the web-features Github Release.
31+ type V3Parser struct {}
32+
3033var ErrUnexpectedFormat = errors .New ("unexpected format" )
3134
3235var ErrUnableToProcess = errors .New ("unable to process the data" )
3336
34- // rawWebFeaturesJSONData is used to parse the source JSON.
37+ // rawWebFeaturesJSONDataV2 is used to parse the source JSON.
38+ // It holds the features as raw JSON messages to be processed individually.
39+ type rawWebFeaturesJSONDataV2 struct {
40+ Browsers web_platform_dx__web_features.Browsers `json:"browsers"`
41+ Groups map [string ]web_platform_dx__web_features.GroupData `json:"groups"`
42+ Snapshots map [string ]web_platform_dx__web_features.SnapshotData `json:"snapshots"`
43+ Features map [string ]web_platform_dx__web_features.FeatureValue `json:"features"`
44+ }
45+
46+ // rawWebFeaturesJSONDataV3 is used to parse the source JSON.
3547// It holds the features as raw JSON messages to be processed individually.
36- type rawWebFeaturesJSONData struct {
48+ type rawWebFeaturesJSONDataV3 struct {
3749 Browsers web_platform_dx__web_features.Browsers `json:"browsers"`
3850 Groups map [string ]web_platform_dx__web_features.GroupData `json:"groups"`
3951 Snapshots map [string ]web_platform_dx__web_features.SnapshotData `json:"snapshots"`
4052 // TODO: When we move to v3, we will change Features to being json.RawMessage
41- Features map [string ]web_platform_dx__web_features.FeatureValue `json:"features"`
53+ Features json.RawMessage `json:"features"`
54+ }
55+
56+ // featureKindPeek is a small helper struct to find the discriminator value in V3.
57+ type featureKindPeek struct {
58+ Kind string `json:"kind"`
4259}
4360
4461// Parse expects the raw bytes for a map of string to
@@ -47,7 +64,7 @@ type rawWebFeaturesJSONData struct {
4764// It will consume the readcloser and close it.
4865func (p Parser ) Parse (in io.ReadCloser ) (* webdxfeaturetypes.ProcessedWebFeaturesData , error ) {
4966 defer in .Close ()
50- var source rawWebFeaturesJSONData
67+ var source rawWebFeaturesJSONDataV2
5168 decoder := json .NewDecoder (in )
5269 err := decoder .Decode (& source )
5370 if err != nil {
@@ -59,7 +76,28 @@ func (p Parser) Parse(in io.ReadCloser) (*webdxfeaturetypes.ProcessedWebFeatures
5976 return processedData , nil
6077}
6178
62- func postProcess (data * rawWebFeaturesJSONData ) * webdxfeaturetypes.ProcessedWebFeaturesData {
79+ // Parse expects the raw bytes for a map of string to
80+ // https://github.com/web-platform-dx/web-features/blob/main/schemas/defs.schema.json
81+ // The string is the feature ID.
82+ // It will consume the readcloser and close it.
83+ func (p V3Parser ) Parse (in io.ReadCloser ) (* webdxfeaturetypes.ProcessedWebFeaturesData , error ) {
84+ defer in .Close ()
85+ var source rawWebFeaturesJSONDataV3
86+ decoder := json .NewDecoder (in )
87+ err := decoder .Decode (& source )
88+ if err != nil {
89+ return nil , errors .Join (ErrUnexpectedFormat , err )
90+ }
91+
92+ processedData , err := postProcessV3 (& source )
93+ if err != nil {
94+ return nil , errors .Join (ErrUnableToProcess , err )
95+ }
96+
97+ return processedData , nil
98+ }
99+
100+ func postProcess (data * rawWebFeaturesJSONDataV2 ) * webdxfeaturetypes.ProcessedWebFeaturesData {
63101 featureKinds := postProcessFeatureValue (data .Features )
64102
65103 return & webdxfeaturetypes.ProcessedWebFeaturesData {
@@ -70,6 +108,90 @@ func postProcess(data *rawWebFeaturesJSONData) *webdxfeaturetypes.ProcessedWebFe
70108 }
71109}
72110
111+ func postProcessV3 (data * rawWebFeaturesJSONDataV3 ) (* webdxfeaturetypes.ProcessedWebFeaturesData , error ) {
112+ featureKinds , err := postProcessFeatureValueV3 (data .Features )
113+ if err != nil {
114+ return nil , err
115+ }
116+
117+ return & webdxfeaturetypes.ProcessedWebFeaturesData {
118+ Browsers : data .Browsers ,
119+ Groups : data .Groups ,
120+ Snapshots : data .Snapshots ,
121+ Features : featureKinds ,
122+ }, nil
123+ }
124+
125+ func postProcessFeatureValueV3 (data json.RawMessage ) (* webdxfeaturetypes.FeatureKinds , error ) {
126+ featureKinds := webdxfeaturetypes.FeatureKinds {
127+ Data : nil ,
128+ Moved : nil ,
129+ Split : nil ,
130+ }
131+
132+ featureRawMessageMap := make (map [string ]json.RawMessage )
133+
134+ err := json .Unmarshal (data , & featureRawMessageMap )
135+ if err != nil {
136+ return nil , err
137+ }
138+
139+ for id , rawFeature := range featureRawMessageMap {
140+ // Peek inside the raw JSON to find the "kind"
141+ var peek featureKindPeek
142+ if err := json .Unmarshal (rawFeature , & peek ); err != nil {
143+ // Skip or log features that don't have a 'kind' field
144+ continue
145+ }
146+
147+ // Switch on the explicit "kind" to unmarshal into the correct type
148+ switch peek .Kind {
149+ case string (web_platform_dx__web_features .Feature ):
150+ if featureKinds .Data == nil {
151+ featureKinds .Data = make (map [string ]web_platform_dx__web_features.FeatureValue )
152+ }
153+ var value web_platform_dx__web_features.FeatureValue
154+ if err := json .Unmarshal (rawFeature , & value ); err != nil {
155+ return nil , err
156+ }
157+ // Run your existing post-processing logic
158+ featureKinds .Data [id ] = web_platform_dx__web_features.FeatureValue {
159+ Caniuse : postProcessStringOrStringArray (value .Caniuse ),
160+ CompatFeatures : value .CompatFeatures ,
161+ Description : value .Description ,
162+ DescriptionHTML : value .DescriptionHTML ,
163+ Group : postProcessStringOrStringArray (value .Group ),
164+ Name : value .Name ,
165+ Snapshot : postProcessStringOrStringArray (value .Snapshot ),
166+ Spec : postProcessStringOrStringArray (value .Spec ),
167+ Status : postProcessStatus (value .Status ),
168+ Discouraged : value .Discouraged ,
169+ }
170+
171+ case string (web_platform_dx__web_features .Moved ):
172+ if featureKinds .Moved == nil {
173+ featureKinds .Moved = make (map [string ]web_platform_dx__web_features.FeatureMovedData )
174+ }
175+ var value web_platform_dx__web_features.FeatureMovedData
176+ if err := json .Unmarshal (rawFeature , & value ); err != nil {
177+ return nil , err
178+ }
179+ featureKinds .Moved [id ] = value
180+
181+ case string (web_platform_dx__web_features .Split ):
182+ if featureKinds .Split == nil {
183+ featureKinds .Split = make (map [string ]web_platform_dx__web_features.FeatureSplitData )
184+ }
185+ var value web_platform_dx__web_features.FeatureSplitData
186+ if err := json .Unmarshal (rawFeature , & value ); err != nil {
187+ return nil , err
188+ }
189+ featureKinds .Split [id ] = value
190+ }
191+ }
192+
193+ return & featureKinds , nil
194+ }
73195func postProcessFeatureValue (
74196 data map [string ]web_platform_dx__web_features.FeatureValue ) * webdxfeaturetypes.FeatureKinds {
75197 featureKinds := webdxfeaturetypes.FeatureKinds {
0 commit comments