@@ -74,25 +74,18 @@ func NewView(path string) (*View, error) {
7474 return & view , nil
7575}
7676
77- func (b * View ) ApplyV2 (f * File ) ([]ScopedValues , error ) {
78- found := []ScopedValues {}
79-
77+ func (b * View ) Apply (f * File ) ([]ScopedValues , error ) {
8078 value , err := fileToValue (f )
8179 if err != nil {
8280 return nil , err
8381 }
8482
83+ found := make ([]ScopedValues , 0 , len (b .Scopes ))
8584 for _ , s := range b .Scopes {
86- selected , verr := v2dasel .Select (value , s .Expr )
87- if verr != nil {
88- return found , verr
89- }
90-
91- values := []string {}
92- for _ , v := range selected {
93- values = append (values , v .String ())
85+ values , err := selectStrings (value , s .Expr )
86+ if err != nil {
87+ return nil , fmt .Errorf ("processing scope %q: %w" , s .Name , err )
9488 }
95-
9689 found = append (found , ScopedValues {
9790 Scope : s .Name ,
9891 Values : values ,
@@ -103,55 +96,75 @@ func (b *View) ApplyV2(f *File) ([]ScopedValues, error) {
10396 return found , nil
10497}
10598
106- func (b * View ) Apply (f * File ) ([]ScopedValues , error ) {
107- found := []ScopedValues {}
108-
109- value , err := fileToValue (f )
99+ func selectStrings (value DaselValue , expr string ) ([]string , error ) {
100+ selected , _ , err := dasel .Select (context .Background (), value , expr )
110101 if err != nil {
111- return nil , err
102+ return selectStringsV2 ( value , expr )
112103 }
113104
114- for _ , s := range b .Scopes {
115- selected , _ , verr := dasel .Select (context .Background (), value , s .Expr )
116- if verr != nil {
117- // We failed; try to see if the old version of dasel can handle it.
118- v2found , v2err := b .ApplyV2 (f )
119- if v2err != nil {
120- // If the old version also fails, return the original error.
121- return nil , verr
122- }
123- return v2found , nil
105+ outer , ok := selected .([]any )
106+ if ! ok {
107+ return nil , fmt .Errorf ("expected []any, got %T" , selected )
108+ }
109+
110+ // Unwrap single-element wrapper if present.
111+ if len (outer ) == 1 {
112+ if inner , ok := outer [0 ].([]any ); ok {
113+ outer = inner
124114 }
115+ }
125116
126- if selectResults , ok := selected .([]any ); ok {
127- if len (selectResults ) == 1 {
128- if inner , iok := selectResults [0 ].([]any ); iok {
129- selectResults = inner
130- }
131- } else {
132- return nil , fmt .Errorf ("unexpected result type for scope %s: expected array, got %T" , s .Name , selected )
133- }
134-
135- values := []string {}
136- for _ , v := range selectResults {
137- if str , sok := v .(string ); sok {
138- values = append (values , str )
139- }
140- }
141-
142- found = append (found , ScopedValues {
143- Scope : s .Name ,
144- Values : values ,
145- Format : s .Type ,
146- })
117+ results := make ([]string , 0 , len (outer ))
118+ for _ , v := range outer {
119+ if str , ok := v .(string ); ok {
120+ results = append (results , str )
147121 }
148122 }
123+ return results , nil
124+ }
149125
150- return found , nil
126+ func selectStringsV2 (value DaselValue , expr string ) ([]string , error ) {
127+ selected , err := v2dasel .Select (value , expr )
128+ if err != nil {
129+ return nil , err
130+ }
131+ results := make ([]string , 0 , len (selected ))
132+ for _ , v := range selected {
133+ results = append (results , v .String ())
134+ }
135+ return results , nil
136+ }
137+
138+ // normalize recursively converts map[interface{}]interface{} (produced by
139+ // gopkg.in/yaml.v2) to map[string]any so that Dasel v3 can traverse the
140+ // document without choking on interface{} map keys.
141+ func normalize (v any ) any {
142+ switch v := v .(type ) {
143+ case map [interface {}]interface {}:
144+ out := make (map [string ]any , len (v ))
145+ for k , val := range v {
146+ out [fmt .Sprintf ("%v" , k )] = normalize (val )
147+ }
148+ return out
149+ case map [string ]any :
150+ out := make (map [string ]any , len (v ))
151+ for k , val := range v {
152+ out [k ] = normalize (val )
153+ }
154+ return out
155+ case []any :
156+ out := make ([]any , len (v ))
157+ for i , val := range v {
158+ out [i ] = normalize (val )
159+ }
160+ return out
161+ default :
162+ return v
163+ }
151164}
152165
153166func fileToValue (f * File ) (DaselValue , error ) {
154- var value DaselValue
167+ var raw any
155168
156169 // We replace block chomping indicators with a pipe to ensure that
157170 // newlines are preserved.
@@ -164,23 +177,28 @@ func fileToValue(f *File) (DaselValue, error) {
164177 contents := []byte (text )
165178 switch f .RealExt {
166179 case ".json" :
167- err := json .Unmarshal (contents , & value )
180+ err := json .Unmarshal (contents , & raw )
168181 if err != nil {
169182 return nil , err
170183 }
171184 case ".yml" , ".yaml" :
172- err := yaml .Unmarshal (contents , & value )
185+ err := yaml .Unmarshal (contents , & raw )
173186 if err != nil {
174187 return nil , err
175188 }
176189 case ".toml" :
177- err := toml .Unmarshal (contents , & value )
190+ err := toml .Unmarshal (contents , & raw )
178191 if err != nil {
179192 return nil , err
180193 }
181194 default :
182195 return nil , errors .New ("unsupported file type" )
183196 }
184197
198+ value , ok := normalize (raw ).(map [string ]any )
199+ if ! ok {
200+ return nil , errors .New ("document root is not an object" )
201+ }
202+
185203 return value , nil
186204}
0 commit comments