Skip to content

Commit c3ffb45

Browse files
authored
Add documentation to UnmarshalJSON implementations (#179)
1 parent ef5e0b8 commit c3ffb45

File tree

12 files changed

+827
-18
lines changed

12 files changed

+827
-18
lines changed

config.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,10 @@ func (c *Config) Validate() error {
3232
return nil
3333
}
3434

35+
// UnmarshalJSON implements json.Unmarshaler for Config.
36+
//
37+
// As per established convention this method should only ever
38+
// be invoked *indirectly* via [encoding/json] library.
3539
func (c *Config) UnmarshalJSON(b []byte) error {
3640
type rawConfig Config
3741
var config rawConfig

expression.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,9 @@ type ExpressionData struct {
4747
}
4848

4949
// UnmarshalJSON implements json.Unmarshaler for Expression.
50+
//
51+
// As per established convention this method should only ever
52+
// be invoked *indirectly* via [encoding/json] library.
5053
func (e *Expression) UnmarshalJSON(b []byte) error {
5154
result := new(ExpressionData)
5255

metadata.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,10 @@ func (f *MetadataFunctions) Validate() error {
5757
return nil
5858
}
5959

60+
// UnmarshalJSON implements json.Unmarshaler for MetadataFunctions.
61+
//
62+
// As per established convention this method should only ever
63+
// be invoked *indirectly* via [encoding/json] library.
6064
func (f *MetadataFunctions) UnmarshalJSON(b []byte) error {
6165
type rawFunctions MetadataFunctions
6266
var functions rawFunctions

parse_test.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ const testFixtureDir = "testdata"
1818
const testGoldenPlanFileName = "plan.json"
1919
const testGoldenStateFileName = "state.json"
2020
const testGoldenSchemasFileName = "schemas.json"
21+
const testInvalidDir = "invalid"
2122

2223
func testParse(t *testing.T, filename string, typ reflect.Type) {
2324
entries, err := os.ReadDir(testFixtureDir)
@@ -31,6 +32,10 @@ func testParse(t *testing.T, filename string, typ reflect.Type) {
3132
}
3233

3334
t.Run(e.Name(), func(t *testing.T) {
35+
if e.Name() == testInvalidDir {
36+
t.Skip("Skipping known invalid test fixture")
37+
}
38+
3439
expected, err := os.ReadFile(filepath.Join(testFixtureDir, e.Name(), filename))
3540
if err != nil {
3641
if os.IsNotExist(err) {

plan.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,10 @@ func (p *Plan) Validate() error {
142142
return nil
143143
}
144144

145+
// UnmarshalJSON implements json.Unmarshaler for Plan.
146+
//
147+
// As per established convention this method should only ever
148+
// be invoked *indirectly* via [encoding/json] library.
145149
func (p *Plan) UnmarshalJSON(b []byte) error {
146150
type rawPlan Plan
147151
var plan rawPlan

plan_test.go

Lines changed: 43 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ package tfjson
55

66
import (
77
"encoding/json"
8+
"io"
89
"os"
910
"reflect"
1011
"testing"
@@ -187,7 +188,7 @@ func TestPlan_UnmarshalJSON(t *testing.T) {
187188
t.Fatal(err)
188189
}
189190

190-
testCases := map[string]struct {
191+
numericsTestCases := map[string]struct {
191192
useJSONNumber bool
192193
expected any
193194
}{
@@ -200,17 +201,15 @@ func TestPlan_UnmarshalJSON(t *testing.T) {
200201
},
201202
}
202203

203-
for name, testCase := range testCases {
204-
name, testCase := name, testCase
205-
204+
for name, testCase := range numericsTestCases {
206205
t.Run(name, func(t *testing.T) {
207206
t.Parallel()
208207

209208
plan := &Plan{}
210209

211210
plan.UseJSONNumber(testCase.useJSONNumber)
212211

213-
err = plan.UnmarshalJSON(b)
212+
err = json.Unmarshal(b, &plan)
214213
if err != nil {
215214
t.Fatal(err)
216215
}
@@ -232,4 +231,43 @@ func TestPlan_UnmarshalJSON(t *testing.T) {
232231
}
233232
})
234233
}
234+
235+
jsonValidationTestCases := map[string]struct {
236+
filePath string
237+
expectError bool
238+
}{
239+
"invalid plan JSON": {
240+
filePath: "testdata/invalid/plan.json",
241+
expectError: true,
242+
},
243+
"valid plan JSON": {
244+
filePath: "testdata/basic/plan.json",
245+
},
246+
}
247+
248+
for tn, tc := range jsonValidationTestCases {
249+
t.Run(tn, func(t *testing.T) {
250+
f, err := os.Open(tc.filePath)
251+
if err != nil {
252+
t.Fatal(err)
253+
}
254+
defer f.Close()
255+
256+
b, err := io.ReadAll(f)
257+
if err != nil {
258+
t.Fatal(err)
259+
}
260+
261+
var plan Plan
262+
err = json.Unmarshal(b, &plan)
263+
264+
if tc.expectError && err == nil {
265+
t.Fatalf("expected error; got none")
266+
}
267+
268+
if !tc.expectError && err != nil {
269+
t.Errorf("expected no error, got %q", err.Error())
270+
}
271+
})
272+
}
235273
}

schemas.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,10 @@ func (p *ProviderSchemas) Validate() error {
6060
return nil
6161
}
6262

63+
// UnmarshalJSON implements json.Unmarshaler for ProviderSchemas.
64+
//
65+
// As per established convention this method should only ever
66+
// be invoked *indirectly* via [encoding/json] library.
6367
func (p *ProviderSchemas) UnmarshalJSON(b []byte) error {
6468
type rawSchemas ProviderSchemas
6569
var schemas rawSchemas

state.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,10 @@ func (s *State) Validate() error {
7878
return nil
7979
}
8080

81+
// UnmarshalJSON implements json.Unmarshaler for State.
82+
//
83+
// As per established convention this method should only ever
84+
// be invoked *indirectly* via [encoding/json] library.
8185
func (s *State) UnmarshalJSON(b []byte) error {
8286
type rawState State
8387
var state rawState

state_test.go

Lines changed: 35 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -42,22 +42,44 @@ func TestStateValidate_raw(t *testing.T) {
4242
}
4343
}
4444

45-
func TestStateUnmarshal_valid(t *testing.T) {
46-
f, err := os.Open("testdata/no_changes/state.json")
47-
if err != nil {
48-
t.Fatal(err)
45+
func TestStateUnmarshal(t *testing.T) {
46+
testCases := map[string]struct {
47+
filePath string
48+
expectError bool
49+
}{
50+
"valid state JSON": {
51+
filePath: "testdata/no_changes/state.json",
52+
},
53+
"invalid state JSON": {
54+
filePath: "testdata/invalid/state.json",
55+
expectError: true,
56+
},
4957
}
50-
defer f.Close()
5158

52-
b, err := io.ReadAll(f)
53-
if err != nil {
54-
t.Fatal(err)
55-
}
59+
for tn, tc := range testCases {
60+
t.Run(tn, func(t *testing.T) {
61+
f, err := os.Open(tc.filePath)
62+
if err != nil {
63+
t.Fatal(err)
64+
}
65+
defer f.Close()
5666

57-
var state State
58-
err = json.Unmarshal(b, &state)
59-
if err != nil {
60-
t.Fatal(err)
67+
b, err := io.ReadAll(f)
68+
if err != nil {
69+
t.Fatal(err)
70+
}
71+
72+
var state State
73+
err = json.Unmarshal(b, &state)
74+
75+
if tc.expectError && err == nil {
76+
t.Fatalf("expected error; got none")
77+
}
78+
79+
if !tc.expectError && err != nil {
80+
t.Errorf("expected no error, got %q", err.Error())
81+
}
82+
})
6183
}
6284
}
6385

0 commit comments

Comments
 (0)