Repository: ogen-go/ogen
Pull request #584 (2022-09-23 01:45:39)

fix(jsonschema): handle YAML-to-JSON conversion correctly

codecov[bot]: # [Codecov](https://codecov.io/gh/ogen-go/ogen/pull/584?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=ogen-go) Report
Base: **72.09**% // Head: **72.06**% // Decreases project coverage by **`-0.03%`** :warning:
> Coverage data is based on head [(`053d560`)](https://codecov.io/gh/ogen-go/ogen/pull/584?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=ogen-go) compared to base [(`d43685c`)](https://codecov.io/gh/ogen-go/ogen/commit/d43685ce652de8368b0fac25af2de8efbb4aea90?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=ogen-go).
> Patch coverage: 50.00% of modified lines in pull request are covered.

> :exclamation: Current head 053d560 differs from pull request most recent head 47c9ad1. Consider uploading reports for the commit 47c9ad1 to get more accurate results

<details><summary>Additional details and impacted files</summary>


```diff
@@            Coverage Diff             @@
##             main     #584      +/-   ##
==========================================
- Coverage   72.09%   72.06%   -0.04%     
==========================================
  Files         159      159              
  Lines       11340    11344       +4     
==========================================
- Hits         8176     8175       -1     
- Misses       2739     2742       +3     
- Partials      425      427       +2     
```


| [Impacted Files](https://codecov.io/gh/ogen-go/ogen/pull/584?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=ogen-go) | Coverage Δ | |
|---|---|---|
| [jsonschema/raw\_value.go](https://codecov.io/gh/ogen-go/ogen/pull/584/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=ogen-go#diff-anNvbnNjaGVtYS9yYXdfdmFsdWUuZ28=) | `43.24% <50.00%> (-2.22%)` | :arrow_down: |
| [gen/gen\_contents.go](https://codecov.io/gh/ogen-go/ogen/pull/584/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=ogen-go#diff-Z2VuL2dlbl9jb250ZW50cy5nbw==) | `72.20% <0.00%> (-0.68%)` | :arrow_down: |

Help us with your feedback. Take ten seconds to tell us [how you rate us](https://about.codecov.io/nps?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=ogen-go). Have a feature suggestion? [Share it here.](https://app.codecov.io/gh/feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=ogen-go)

</details>

[:umbrella: View full report at Codecov](https://codecov.io/gh/ogen-go/ogen/pull/584?src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=ogen-go).   
:loudspeaker: Do you have feedback about the report comment? [Let us know in this issue](https://about.codecov.io/codecov-pr-comment-feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=ogen-go).


Patch:
diff --git a/examples/go.mod b/examples/go.mod
index 668dea81..f28c9939 100644
--- a/examples/go.mod
+++ b/examples/go.mod
@@ -19,6 +19,7 @@ require (
 require (
 	github.com/davecgh/go-spew v1.1.1 // indirect
 	github.com/fatih/color v1.13.0 // indirect
+	github.com/ghodss/yaml v1.0.0 // indirect
 	github.com/go-faster/yamlx v0.3.6 // indirect
 	github.com/go-logr/logr v1.2.3 // indirect
 	github.com/go-logr/stdr v1.2.2 // indirect
@@ -29,6 +30,7 @@ require (
 	go.uber.org/atomic v1.9.0 // indirect
 	golang.org/x/sync v0.0.0-20220819030929-7fc1605a5dde // indirect
 	golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10 // indirect
+	gopkg.in/yaml.v2 v2.4.0 // indirect
 	gopkg.in/yaml.v3 v3.0.1 // indirect
 )
 
diff --git a/examples/go.sum b/examples/go.sum
index 5b72049d..974cf1fe 100644
--- a/examples/go.sum
+++ b/examples/go.sum
@@ -5,6 +5,7 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
 github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w=
 github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
 github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=
+github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
 github.com/go-faster/errors v0.6.1 h1:nNIPOBkprlKzkThvS/0YaX8Zs9KewLCOSFQS5BU06FI=
 github.com/go-faster/errors v0.6.1/go.mod h1:5MGV2/2T9yvlrbhe9pD9LO5Z/2zCSq2T8j+Jpi2LAyY=
 github.com/go-faster/jx v0.39.0 h1:5FmkTOHKKCsnAbSLzQclORDNndC9BY77UqB+HLsHDd0=
@@ -68,6 +69,7 @@ golang.org/x/tools v0.1.12 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
 gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
+gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
 gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
 gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
 gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
diff --git a/jsonschema/raw_value.go b/jsonschema/raw_value.go
index 643ba19c..4bce36d9 100644
--- a/jsonschema/raw_value.go
+++ b/jsonschema/raw_value.go
@@ -3,6 +3,8 @@ package jsonschema
 import (
 	"encoding/json"
 
+	helperyaml "github.com/ghodss/yaml"
+	"github.com/go-faster/errors"
 	yaml "github.com/go-faster/yamlx"
 )
 
@@ -41,7 +43,12 @@ func (n *RawValue) UnmarshalJSON(b []byte) error {
 	return nil
 }
 
-func convertJSONToRawYAML(raw json.RawMessage) (*yaml.Node, error) {
+func convertJSONToRawYAML(raw json.RawMessage) (_ *yaml.Node, rerr error) {
+	defer func() {
+		if rerr != nil {
+			rerr = errors.Wrap(rerr, "convert JSON to YAML")
+		}
+	}()
 	var node yaml.Node
 	if err := yaml.Unmarshal(raw, &node); err != nil {
 		return nil, err
@@ -52,14 +59,15 @@ func convertJSONToRawYAML(raw json.RawMessage) (*yaml.Node, error) {
 	return &node, nil
 }
 
-func convertYAMLtoRawJSON(node *yaml.Node) (json.RawMessage, error) {
-	var tmp any
-	if err := node.Decode(&tmp); err != nil {
-		return nil, err
-	}
-	raw, err := json.Marshal(tmp)
+func convertYAMLtoRawJSON(node *yaml.Node) (_ json.RawMessage, rerr error) {
+	defer func() {
+		if rerr != nil {
+			rerr = errors.Wrap(rerr, "convert YAML to JSON")
+		}
+	}()
+	raw, err := yaml.Marshal(node)
 	if err != nil {
 		return nil, err
 	}
-	return raw, nil
+	return helperyaml.YAMLToJSON(raw)
 }


Test patch:
diff --git a/jsonschema/raw_value_test.go b/jsonschema/raw_value_test.go
new file mode 100644
index 00000000..d4cedb2f
--- /dev/null
+++ b/jsonschema/raw_value_test.go
@@ -0,0 +1,53 @@
+package jsonschema
+
+import (
+	"fmt"
+	"testing"
+
+	yaml "github.com/go-faster/yamlx"
+	"github.com/stretchr/testify/require"
+)
+
+func Test_convertYAMLtoRawJSON(t *testing.T) {
+	mustNode := func(s string) *yaml.Node {
+		var n yaml.Node
+		if err := yaml.Unmarshal([]byte(s), &n); err != nil {
+			t.Fatal(err)
+			return nil
+		}
+		return &n
+	}
+	tests := []struct {
+		node    *yaml.Node
+		want    string
+		wantErr bool
+	}{
+		{mustNode(`1`), `1`, false},
+		{mustNode(`"foo"`), `"foo"`, false},
+		{mustNode(`foo: bar`), `{"foo": "bar"}`, false},
+		{mustNode(`foo: [1, 2, 3]`), `{"foo": [1, 2, 3]}`, false},
+		{mustNode(`10: foo`), `{"10": "foo"}`, false},
+		{&yaml.Node{
+			Kind: yaml.MappingNode,
+			Tag:  "!!map",
+			Content: []*yaml.Node{
+				{Kind: yaml.ScalarNode, Tag: "!!int", Value: "10"},
+				{Kind: yaml.ScalarNode, Tag: "!!str", Value: "foo"},
+			},
+		}, `{"10": "foo"}`, false},
+	}
+	for i, tt := range tests {
+		tt := tt
+		t.Run(fmt.Sprintf("Test%d", i+1), func(t *testing.T) {
+			a := require.New(t)
+
+			got, err := convertYAMLtoRawJSON(tt.node)
+			if tt.wantErr {
+				a.Error(err)
+				return
+			}
+			a.NoError(err)
+			a.JSONEq(tt.want, string(got))
+		})
+	}
+}