Skip to content

Commit

Permalink
Merge pull request #102 from goccy/feature/support-decoding-for-order…
Browse files Browse the repository at this point in the history
…ed-map

Support decoding for MapItem and MapSlice
  • Loading branch information
goccy authored May 28, 2020
2 parents 8dcc157 + ae70017 commit 05f465a
Show file tree
Hide file tree
Showing 2 changed files with 77 additions and 0 deletions.
65 changes: 65 additions & 0 deletions decode.go
Original file line number Diff line number Diff line change
Expand Up @@ -408,8 +408,14 @@ func (d *Decoder) decodeValue(dst reflect.Value, src ast.Node) error {
case reflect.Array:
return d.decodeArray(dst, src)
case reflect.Slice:
if mapSlice, ok := dst.Addr().Interface().(*MapSlice); ok {
return d.decodeMapSlice(mapSlice, src)
}
return d.decodeSlice(dst, src)
case reflect.Struct:
if mapItem, ok := dst.Addr().Interface().(*MapItem); ok {
return d.decodeMapItem(mapItem, src)
}
return d.decodeStruct(dst, src)
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
v := d.nodeToValue(src)
Expand Down Expand Up @@ -882,6 +888,65 @@ func (d *Decoder) decodeSlice(dst reflect.Value, src ast.Node) error {
return nil
}

func (d *Decoder) decodeMapItem(dst *MapItem, src ast.Node) error {
mapNode, err := d.getMapNode(src)
if err != nil {
return errors.Wrapf(err, "failed to get map node")
}
if mapNode == nil {
return nil
}
mapIter := mapNode.MapRange()
if !mapIter.Next() {
return nil
}
key := mapIter.Key()
value := mapIter.Value()
if key.Type() == ast.MergeKeyType {
if err := d.decodeMapItem(dst, value); err != nil {
return errors.Wrapf(err, "failed to decode map with merge key")
}
return nil
}
*dst = MapItem{
Key: d.nodeToValue(key),
Value: d.nodeToValue(value),
}
return nil
}

func (d *Decoder) decodeMapSlice(dst *MapSlice, src ast.Node) error {
mapNode, err := d.getMapNode(src)
if err != nil {
return errors.Wrapf(err, "failed to get map node")
}
if mapNode == nil {
return nil
}
mapSlice := MapSlice{}
mapIter := mapNode.MapRange()
for mapIter.Next() {
key := mapIter.Key()
value := mapIter.Value()
if key.Type() == ast.MergeKeyType {
var m MapSlice
if err := d.decodeMapSlice(&m, value); err != nil {
return errors.Wrapf(err, "failed to decode map with merge key")
}
for _, v := range m {
mapSlice = append(mapSlice, v)
}
continue
}
mapSlice = append(mapSlice, MapItem{
Key: d.nodeToValue(key),
Value: d.nodeToValue(value),
})
}
*dst = mapSlice
return nil
}

func (d *Decoder) decodeMap(dst reflect.Value, src ast.Node) error {
mapNode, err := d.getMapNode(src)
if err != nil {
Expand Down
12 changes: 12 additions & 0 deletions decode_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -566,6 +566,18 @@ func TestDecoder(t *testing.T) {
}{1},
},

{
"a: 1\n",
yaml.MapItem{Key: "a", Value: 1},
},
{
"a: 1\nb: 2\nc: 3\n",
yaml.MapSlice{
{Key: "a", Value: 1},
{Key: "b", Value: 2},
{Key: "c", Value: 3},
},
},
{
"v:\n- A\n- 1\n- B:\n - 2\n - 3\n",
map[string]interface{}{
Expand Down

0 comments on commit 05f465a

Please sign in to comment.