Repository: getsops/sops (language: python)

Issue:
Trailing comment in YAML causes `Error marshaling to json: invalid character '}' looking for beginning of object key string` when output type is JSON
Sops v3.9.1

To reproduce:

```
$ echo -e 'foo: bar\n#Hello world' | sops --input-type yaml --output-type yaml -e /dev/stdin > test.yaml
$ sops -d test.yaml 
foo: bar
#Hello world
$ sops --output-type json --decrypt --input-type yaml test.yaml 
Error dumping file: Error marshaling to json: invalid character '}' looking for beginning of object key string
```




Discussion / hints:
Thanks for reporting this!

I just tested this with 3.9.0, there it also happens. So at least it's not a regression introduced in 3.9.1 :sweat_smile:

Fix patch:
diff --git a/stores/json/store.go b/stores/json/store.go
index e9df1b554..3212b5b32 100644
--- a/stores/json/store.go
+++ b/stores/json/store.go
@@ -186,18 +186,20 @@ func (store Store) encodeValue(v interface{}) ([]byte, error) {
 
 func (store Store) encodeArray(array []interface{}) ([]byte, error) {
 	out := "["
-	for i, item := range array {
+	empty := true
+	for _, item := range array {
 		if _, ok := item.(sops.Comment); ok {
 			continue
 		}
+		if !empty {
+			out += ","
+		}
 		v, err := store.encodeValue(item)
 		if err != nil {
 			return nil, err
 		}
 		out += string(v)
-		if i != len(array)-1 {
-			out += ","
-		}
+		empty = false
 	}
 	out += "]"
 	return []byte(out), nil
@@ -205,10 +207,14 @@ func (store Store) encodeArray(array []interface{}) ([]byte, error) {
 
 func (store Store) encodeTree(tree sops.TreeBranch) ([]byte, error) {
 	out := "{"
-	for i, item := range tree {
+	empty := true
+	for _, item := range tree {
 		if _, ok := item.Key.(sops.Comment); ok {
 			continue
 		}
+		if !empty {
+			out += ","
+		}
 		v, err := store.encodeValue(item.Value)
 		if err != nil {
 			return nil, fmt.Errorf("Error encoding value %s: %s", v, err)
@@ -218,9 +224,7 @@ func (store Store) encodeTree(tree sops.TreeBranch) ([]byte, error) {
 			return nil, fmt.Errorf("Error encoding key %s: %s", k, err)
 		}
 		out += string(k) + `: ` + string(v)
-		if i != len(tree)-1 {
-			out += ","
-		}
+		empty = false
 	}
 	return []byte(out + "}"), nil
 }


Test patch:
diff --git a/stores/json/store_test.go b/stores/json/store_test.go
index eca6d3e96..38f9882b5 100644
--- a/stores/json/store_test.go
+++ b/stores/json/store_test.go
@@ -540,3 +540,70 @@ func TestNoIndent(t *testing.T) {
 	assert.Nil(t, err)
 	assert.Equal(t, expected, string(out))
 }
+
+func TestComments(t *testing.T) {
+	tree := sops.Tree{
+		Branches: sops.TreeBranches{
+			sops.TreeBranch{
+				sops.TreeItem{
+					Key: "foo",
+					Value: []interface{}{
+						sops.Comment{Value: " comment 0"},
+						sops.TreeBranch{
+							sops.TreeItem{
+								Key:   sops.Comment{Value: " comment 1"},
+								Value: nil,
+							},
+							sops.TreeItem{
+								Key:   "foo",
+								Value: 3,
+							},
+							sops.TreeItem{
+								Key:   sops.Comment{Value: " comment 2"},
+								Value: nil,
+							},
+							sops.TreeItem{
+								Key:   sops.Comment{Value: " comment 3"},
+								Value: nil,
+							},
+							sops.TreeItem{
+								Key:   "bar",
+								Value: false,
+							},
+							sops.TreeItem{
+								Key:   sops.Comment{Value: " comment 4"},
+								Value: nil,
+							},
+							sops.TreeItem{
+								Key:   sops.Comment{Value: " comment 5"},
+								Value: nil,
+							},
+						},
+						sops.Comment{Value: " comment 6"},
+						sops.Comment{Value: " comment 7"},
+						2,
+						sops.Comment{Value: " comment 8"},
+						sops.Comment{Value: " comment 9"},
+					},
+				},
+			},
+		},
+	}
+	expected := `{
+  "foo": [
+    {
+      "foo": 3,
+      "bar": false
+    },
+    2
+  ]
+}`
+	store := Store{
+		config: config.JSONStoreConfig{
+			Indent: 2,
+		},
+	}
+	out, err := store.EmitPlainFile(tree.Branches)
+	assert.Nil(t, err)
+	assert.Equal(t, expected, string(out))
+}